Skip to content

Commit b3e8cc9

Browse files
authored
Merge pull request #507 from cv4g/countmin-microbenchmark
Add micro-benchmark for `count_min_sketch`
2 parents 78cc913 + ab1a6c6 commit b3e8cc9

3 files changed

Lines changed: 210 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ if (BUILD_TESTS)
7474
enable_testing()
7575
endif()
7676

77+
option(BUILD_BENCHMARKS "Build benchmarks" OFF)
78+
7779
option(COVERAGE "Enable code coverage reporting (g++/clang only)" OFF)
7880
if(COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
7981
set(CMAKE_BUILD_TYPE "Debug" FORCE)
@@ -121,6 +123,10 @@ add_subdirectory(density)
121123
add_subdirectory(tdigest)
122124
add_subdirectory(filters)
123125

126+
if (BUILD_BENCHMARKS)
127+
add_subdirectory(benchmarks)
128+
endif()
129+
124130
if (WITH_PYTHON)
125131
add_subdirectory(python)
126132
endif()

benchmarks/CMakeLists.txt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
if (NOT TARGET benchmark::benchmark_main)
19+
include(FetchContent)
20+
21+
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Disable google-benchmark tests" FORCE)
22+
set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "Disable google-benchmark gtest tests" FORCE)
23+
set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "Disable google-benchmark install rules" FORCE)
24+
set(BENCHMARK_INSTALL_DOCS OFF CACHE BOOL "Disable google-benchmark documentation install" FORCE)
25+
set(BENCHMARK_ENABLE_WERROR OFF CACHE BOOL "Disable google-benchmark warnings as errors" FORCE)
26+
27+
FetchContent_Declare(
28+
googlebenchmark
29+
GIT_REPOSITORY https://github.com/google/benchmark.git
30+
GIT_TAG v1.7.1
31+
)
32+
33+
FetchContent_MakeAvailable(googlebenchmark)
34+
endif()
35+
36+
add_executable(count_min_sketch_benchmark)
37+
38+
target_link_libraries(count_min_sketch_benchmark
39+
PRIVATE
40+
count
41+
benchmark::benchmark_main
42+
)
43+
44+
set_target_properties(count_min_sketch_benchmark PROPERTIES
45+
CXX_STANDARD_REQUIRED YES
46+
)
47+
48+
target_sources(count_min_sketch_benchmark
49+
PRIVATE
50+
benchmark_count_min_sketch.cpp
51+
)
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include <benchmark/benchmark.h>
21+
#include <count_min.hpp>
22+
23+
#include <cstddef>
24+
#include <cstdint>
25+
#include <string>
26+
#include <vector>
27+
28+
namespace
29+
{
30+
31+
using Sketch = datasketches::count_min_sketch<uint64_t>;
32+
33+
// Roughly 99.9% confidence and 0.1% relative error:
34+
// suggest_num_hashes(0.999) == 7 and suggest_num_buckets(0.001) == 2719.
35+
constexpr uint8_t NUM_HASHES = 7;
36+
constexpr uint32_t NUM_BUCKETS = 2719;
37+
38+
std::vector<uint64_t> makeUInt64Keys(size_t size)
39+
{
40+
std::vector<uint64_t> keys;
41+
keys.reserve(size);
42+
for (size_t i = 0; i < size; ++i)
43+
keys.push_back(static_cast<uint64_t>(i * 0x9e3779b97f4a7c15ULL));
44+
return keys;
45+
}
46+
47+
std::vector<std::string> makeStringKeys(size_t size)
48+
{
49+
std::vector<std::string> keys;
50+
keys.reserve(size);
51+
for (size_t i = 0; i < size; ++i)
52+
keys.push_back("countmin-key-" + std::to_string(i * 2654435761ULL));
53+
return keys;
54+
}
55+
56+
int64_t totalStringBytes(const std::vector<std::string> & keys)
57+
{
58+
int64_t bytes = 0;
59+
for (const auto & key : keys)
60+
bytes += static_cast<int64_t>(key.size());
61+
return bytes;
62+
}
63+
64+
void BM_CountMinUpdateUInt64(benchmark::State & state)
65+
{
66+
const auto keys = makeUInt64Keys(static_cast<size_t>(state.range(0)));
67+
for (auto _ : state)
68+
{
69+
state.PauseTiming();
70+
Sketch sketch(NUM_HASHES, NUM_BUCKETS);
71+
state.ResumeTiming();
72+
73+
for (const auto key : keys)
74+
sketch.update(&key, sizeof(key), 1);
75+
76+
benchmark::ClobberMemory();
77+
benchmark::DoNotOptimize(sketch.get_total_weight());
78+
}
79+
80+
state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(keys.size()));
81+
state.SetBytesProcessed(state.iterations() * static_cast<int64_t>(keys.size() * sizeof(uint64_t)));
82+
}
83+
84+
void BM_CountMinUpdateStringBytes(benchmark::State & state)
85+
{
86+
const auto keys = makeStringKeys(static_cast<size_t>(state.range(0)));
87+
const auto bytes_per_iteration = totalStringBytes(keys);
88+
89+
for (auto _ : state)
90+
{
91+
state.PauseTiming();
92+
Sketch sketch(NUM_HASHES, NUM_BUCKETS);
93+
state.ResumeTiming();
94+
95+
for (const auto & key : keys)
96+
sketch.update(key.data(), key.size(), 1);
97+
98+
benchmark::ClobberMemory();
99+
benchmark::DoNotOptimize(sketch.get_total_weight());
100+
}
101+
102+
state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(keys.size()));
103+
state.SetBytesProcessed(state.iterations() * bytes_per_iteration);
104+
}
105+
106+
void BM_CountMinEstimateUInt64(benchmark::State & state)
107+
{
108+
const auto keys = makeUInt64Keys(static_cast<size_t>(state.range(0)));
109+
Sketch sketch(NUM_HASHES, NUM_BUCKETS);
110+
for (const auto key : keys)
111+
sketch.update(&key, sizeof(key), 1);
112+
113+
uint64_t sum = 0;
114+
for (auto _ : state)
115+
{
116+
for (const auto key : keys)
117+
sum += sketch.get_estimate(&key, sizeof(key));
118+
119+
benchmark::DoNotOptimize(sum);
120+
}
121+
122+
state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(keys.size()));
123+
state.SetBytesProcessed(state.iterations() * static_cast<int64_t>(keys.size() * sizeof(uint64_t)));
124+
}
125+
126+
void BM_CountMinEstimateStringBytes(benchmark::State & state)
127+
{
128+
const auto keys = makeStringKeys(static_cast<size_t>(state.range(0)));
129+
const auto bytes_per_iteration = totalStringBytes(keys);
130+
131+
Sketch sketch(NUM_HASHES, NUM_BUCKETS);
132+
for (const auto & key : keys)
133+
sketch.update(key.data(), key.size(), 1);
134+
135+
uint64_t sum = 0;
136+
for (auto _ : state)
137+
{
138+
for (const auto & key : keys)
139+
sum += sketch.get_estimate(key.data(), key.size());
140+
141+
benchmark::DoNotOptimize(sum);
142+
}
143+
144+
state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(keys.size()));
145+
state.SetBytesProcessed(state.iterations() * bytes_per_iteration);
146+
}
147+
148+
}
149+
150+
BENCHMARK(BM_CountMinUpdateUInt64)->RangeMultiplier(8)->Range(1024, 65536);
151+
BENCHMARK(BM_CountMinUpdateStringBytes)->RangeMultiplier(8)->Range(1024, 65536);
152+
BENCHMARK(BM_CountMinEstimateUInt64)->RangeMultiplier(8)->Range(1024, 65536);
153+
BENCHMARK(BM_CountMinEstimateStringBytes)->RangeMultiplier(8)->Range(1024, 65536);

0 commit comments

Comments
 (0)