Skip to content

Commit 837fe9d

Browse files
committed
Add micro-benchmark for count_min_sketch
1 parent 4014233 commit 837fe9d

3 files changed

Lines changed: 208 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: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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::DoNotOptimize(sketch.get_total_weight());
77+
}
78+
79+
state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(keys.size()));
80+
state.SetBytesProcessed(state.iterations() * static_cast<int64_t>(keys.size() * sizeof(uint64_t)));
81+
}
82+
83+
void BM_CountMinUpdateStringBytes(benchmark::State & state)
84+
{
85+
const auto keys = makeStringKeys(static_cast<size_t>(state.range(0)));
86+
const auto bytes_per_iteration = totalStringBytes(keys);
87+
88+
for (auto _ : state)
89+
{
90+
state.PauseTiming();
91+
Sketch sketch(NUM_HASHES, NUM_BUCKETS);
92+
state.ResumeTiming();
93+
94+
for (const auto & key : keys)
95+
sketch.update(key.data(), key.size(), 1);
96+
97+
benchmark::DoNotOptimize(sketch.get_total_weight());
98+
}
99+
100+
state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(keys.size()));
101+
state.SetBytesProcessed(state.iterations() * bytes_per_iteration);
102+
}
103+
104+
void BM_CountMinEstimateUInt64(benchmark::State & state)
105+
{
106+
const auto keys = makeUInt64Keys(static_cast<size_t>(state.range(0)));
107+
Sketch sketch(NUM_HASHES, NUM_BUCKETS);
108+
for (const auto key : keys)
109+
sketch.update(&key, sizeof(key), 1);
110+
111+
uint64_t sum = 0;
112+
for (auto _ : state)
113+
{
114+
for (const auto key : keys)
115+
sum += sketch.get_estimate(&key, sizeof(key));
116+
117+
benchmark::DoNotOptimize(sum);
118+
}
119+
120+
state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(keys.size()));
121+
state.SetBytesProcessed(state.iterations() * static_cast<int64_t>(keys.size() * sizeof(uint64_t)));
122+
}
123+
124+
void BM_CountMinEstimateStringBytes(benchmark::State & state)
125+
{
126+
const auto keys = makeStringKeys(static_cast<size_t>(state.range(0)));
127+
const auto bytes_per_iteration = totalStringBytes(keys);
128+
129+
Sketch sketch(NUM_HASHES, NUM_BUCKETS);
130+
for (const auto & key : keys)
131+
sketch.update(key.data(), key.size(), 1);
132+
133+
uint64_t sum = 0;
134+
for (auto _ : state)
135+
{
136+
for (const auto & key : keys)
137+
sum += sketch.get_estimate(key.data(), key.size());
138+
139+
benchmark::DoNotOptimize(sum);
140+
}
141+
142+
state.SetItemsProcessed(state.iterations() * static_cast<int64_t>(keys.size()));
143+
state.SetBytesProcessed(state.iterations() * bytes_per_iteration);
144+
}
145+
146+
}
147+
148+
BENCHMARK(BM_CountMinUpdateUInt64)->RangeMultiplier(8)->Range(1024, 65536);
149+
BENCHMARK(BM_CountMinUpdateStringBytes)->RangeMultiplier(8)->Range(1024, 65536);
150+
BENCHMARK(BM_CountMinEstimateUInt64)->RangeMultiplier(8)->Range(1024, 65536);
151+
BENCHMARK(BM_CountMinEstimateStringBytes)->RangeMultiplier(8)->Range(1024, 65536);

0 commit comments

Comments
 (0)