blob: 5c1c9e66e6d81c7ea041b19745cabc08448d4d88 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include "util/benchmark.h"
#include "util/cpu-info.h"
#include "util/bitmap.h"
#include "common/names.h"
using namespace std;
using namespace impala;
// Tests Bitmap performance on three tasks:
//
// 1. Construct/destruct pairs
// 2. Set an index to true with modulo on Bitmap size. In other words,
// bm.Set(_ % bm.num_bits(), true)
// 3. Get(_ % bm.num_bits())
//
// Machine Info: Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
// initialize: Function Rate (iters/ms) Comparison
// ----------------------------------------------------------------------
// size 1000 5.188e+04 1X
// size 10000 2.834e+04 0.5463X
// size 100000 4795 0.09242X
// size 1000000 340.3 0.006558X
// size 10000000 24.63 0.0004746X
// size 100000000 1.157 2.229e-05X
// size 1000000000 0.08224 1.585e-06X
//
// set: Function Rate (iters/ms) Comparison
// ----------------------------------------------------------------------
// size 1000 1.144e+05 1X
// size 10000 1.155e+05 1.01X
// size 100000 1.168e+05 1.021X
// size 1000000 1.142e+05 0.9981X
// size 10000000 9.789e+04 0.8559X
// size 100000000 3.479e+04 0.3042X
// size 1000000000 2.985e+04 0.261X
//
// get: Function Rate (iters/ms) Comparison
// ----------------------------------------------------------------------
// size 1000 1.231e+05 1X
// size 10000 1.245e+05 1.011X
// size 100000 1.251e+05 1.016X
// size 1000000 1.249e+05 1.014X
// size 10000000 1.068e+05 0.867X
// size 100000000 3.598e+04 0.2922X
// size 1000000000 3.072e+04 0.2495X
// Make a random non-negative int64_t, avoiding the absent high bit and the low-entropy
// low bits produced by rand().
int64_t MakeNonNegativeRand() {
int64_t result = (rand() >> 8) & 0x7fff;
result <<= 16;
result |= (rand() >> 8) & 0xffff;
result <<= 16;
result |= (rand() >> 8) & 0xffff;
result <<= 15;
result |= (rand() >> 8) & 0xffff;
return result;
}
// Just benchmark the constructor and destructor cost
namespace initialize {
void Benchmark(int batch_size, void* data) {
int64_t * d = reinterpret_cast<int64_t*>(data);
for (int i = 0; i < batch_size; ++i) {
Bitmap bm(*d);
}
}
} // namespace initialize
// Benchmark insert
namespace set {
struct TestData {
explicit TestData(int64_t size) : bm(size), data(1ull << 20) {
for (size_t i = 0; i < data.size(); ++i) {
data[i] = MakeNonNegativeRand();
}
}
Bitmap bm;
vector<int64_t> data;
};
void Benchmark(int batch_size, void* data) {
TestData* d = reinterpret_cast<TestData*>(data);
for (int i = 0; i < batch_size; ++i) {
d->bm.Set(d->data[i & (d->data.size() - 1)] % d->bm.num_bits(), true);
}
}
} // namespace set
namespace get {
struct TestData {
TestData(int64_t size)
: bm(size), data (1ull << 20) {
for (size_t i = 0; i < size/2; ++i) {
bm.Set(MakeNonNegativeRand() % size, true);
}
for (size_t i = 0; i < data.size(); ++i) {
data[i] = MakeNonNegativeRand();
}
}
Bitmap bm;
vector<int64_t> data;
// Used only to avoid the compiler optimizing out the results of Bitmap::Get()
size_t result;
};
void Benchmark(int batch_size, void* data) {
TestData* d = reinterpret_cast<TestData*>(data);
for (int i = 0; i < batch_size; ++i) {
d->result += d->bm.Get(d->data[i & (d->data.size() - 1)] % d->bm.num_bits());
}
}
} // namespace get
int main(int argc, char **argv) {
CpuInfo::Init();
cout << endl << Benchmark::GetMachineInfo() << endl;
char name[120];
{
Benchmark suite("initialize");
for (int64_t size = 1000; size <= 1000 * 1000 * 1000; size *= 10) {
int64_t* d = new int64_t(size);
snprintf(name, sizeof(name), "size %10ld", size);
suite.AddBenchmark(name, initialize::Benchmark, d);
}
cout << suite.Measure() << endl;
}
{
Benchmark suite("set");
for (int64_t size = 1000; size <= 1000 * 1000 * 1000; size *= 10) {
set::TestData* d = new set::TestData(size);
snprintf(name, sizeof(name), "size %10ld", size);
suite.AddBenchmark(name, set::Benchmark, d);
}
cout << suite.Measure() << endl;
}
{
Benchmark suite("get");
for (int64_t size = 1000; size <= 1000 * 1000 * 1000; size *= 10) {
get::TestData* d = new get::TestData(size);
snprintf(name, sizeof(name), "size %10ld", size);
suite.AddBenchmark(name, get::Benchmark, d);
}
cout << suite.Measure() << endl;
}
return 0;
}