Skip to content

Commit 01659ce

Browse files
authored
🎨 Clean up pseudo pext benchmarks (#663)
* 🚚 Move lookup benchmark to benchmark directory * 🚚 Move msg handler benchmark to benchmark directory * 🐛 Fix ambiguity in msg handler benchmark * 🎨 Refactor pseudo pext benchmarks to separate algorithms * 🎨 Remove C++23 dependency for pseudo_pext benchmark * 🎨 Generate lookup benchmark data
1 parent f7ea311 commit 01659ce

22 files changed

+640
-50755
lines changed

benchmark/CMakeLists.txt

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,3 @@
1-
add_executable(compilation_benchmark EXCLUDE_FROM_ALL big_nexus.cpp)
2-
3-
target_compile_options(
4-
compilation_benchmark
5-
PRIVATE -ftemplate-backtrace-limit=0
6-
$<$<CXX_COMPILER_ID:Clang>:-fconstexpr-steps=2000000>
7-
$<$<CXX_COMPILER_ID:Clang>:-fbracket-depth=512>
8-
$<$<CXX_COMPILER_ID:Clang>:-ferror-limit=8>
9-
$<$<CXX_COMPILER_ID:GNU>:-fmax-errors=8>)
10-
11-
target_link_libraries(compilation_benchmark PRIVATE cib profile-compilation)
12-
target_include_directories(compilation_benchmark
13-
PRIVATE ${CMAKE_SOURCE_DIR}/test/)
1+
add_subdirectory(cib)
2+
add_subdirectory(lookup)
3+
add_subdirectory(msg)

benchmark/cib/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
add_executable(compilation_benchmark EXCLUDE_FROM_ALL big_nexus.cpp)
2+
3+
target_compile_options(
4+
compilation_benchmark
5+
PRIVATE -ftemplate-backtrace-limit=0
6+
$<$<CXX_COMPILER_ID:Clang>:-fconstexpr-steps=2000000>
7+
$<$<CXX_COMPILER_ID:Clang>:-fbracket-depth=512>
8+
$<$<CXX_COMPILER_ID:Clang>:-ferror-limit=8>
9+
$<$<CXX_COMPILER_ID:GNU>:-fmax-errors=8>)
10+
11+
target_link_libraries(compilation_benchmark PRIVATE cib profile-compilation)
12+
target_include_directories(compilation_benchmark
13+
PRIVATE ${CMAKE_SOURCE_DIR}/test/)
File renamed without changes.

benchmark/lookup/CMakeLists.txt

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
add_versioned_package("gh:boost-ext/mph#v1.0.8")
2+
add_versioned_package("gh:serge-sans-paille/frozen#292a811")
3+
4+
function(gen_lookup_data)
5+
set(oneValueArgs TARGET TYPE SIZE OUTPUT)
6+
cmake_parse_arguments(GEN "" "${oneValueArgs}" "" ${ARGN})
7+
8+
set(script "${CMAKE_SOURCE_DIR}/tools/benchmark/gen_map_data.py")
9+
get_filename_component(DIR "${GEN_OUTPUT}" DIRECTORY)
10+
11+
add_custom_command(
12+
OUTPUT ${GEN_OUTPUT}
13+
COMMAND ${CMAKE_COMMAND} -E make_directory "${DIR}"
14+
COMMAND ${Python3_EXECUTABLE} ${script} --type ${GEN_TYPE} --size
15+
${GEN_SIZE} --output ${GEN_OUTPUT}
16+
DEPENDS ${script}
17+
COMMAND_EXPAND_LISTS)
18+
add_custom_target(${GEN_TARGET} DEPENDS ${GEN_OUTPUT})
19+
endfunction()
20+
21+
set(ALG_NAMES
22+
std_map
23+
std_unordered_map
24+
frozen_map
25+
frozen_unordered_map
26+
pseudo_pext_direct
27+
pseudo_pext_indirect_1
28+
pseudo_pext_indirect_2
29+
pseudo_pext_indirect_3
30+
pseudo_pext_indirect_4
31+
pseudo_pext_indirect_5
32+
pseudo_pext_indirect_6)
33+
34+
set(EXCLUDED_COMBINATIONS
35+
mph_pext_exp_uint32_70
36+
mph_pext_exp_uint32_80
37+
mph_pext_exp_uint32_90
38+
mph_pext_exp_uint32_100
39+
mph_pext_exp_uint32_200
40+
mph_pext_exp_uint32_300
41+
mph_pext_exp_uint32_400
42+
mph_pext_exp_uint32_500
43+
mph_pext_exp_uint32_600
44+
mph_pext_exp_uint32_700
45+
mph_pext_exp_uint32_800
46+
mph_pext_exp_uint32_900
47+
mph_pext_exp_uint32_1000
48+
mph_pext_exp_uint16_70
49+
mph_pext_exp_uint16_80
50+
mph_pext_exp_uint16_90
51+
mph_pext_exp_uint16_100
52+
mph_pext_exp_uint16_200
53+
mph_pext_exp_uint16_300
54+
mph_pext_exp_uint16_400
55+
mph_pext_exp_uint16_500
56+
mph_pext_exp_uint16_600
57+
mph_pext_exp_uint16_700
58+
mph_pext_exp_uint16_800
59+
mph_pext_exp_uint16_900
60+
mph_pext_exp_uint16_1000)
61+
62+
function(gen_pp_benchmarks)
63+
set(oneValueArgs TYPE SIZE)
64+
cmake_parse_arguments(BM "" "${oneValueArgs}" "" ${ARGN})
65+
66+
set(DATASET exp_${BM_TYPE}_${BM_SIZE})
67+
set(HEADER "${CMAKE_BINARY_DIR}/benchmark/generated/${DATASET}.hpp")
68+
set(DATA_TARGET "bm_lookup_data_${DATASET}")
69+
gen_lookup_data(
70+
TARGET
71+
${DATA_TARGET}
72+
TYPE
73+
${BM_TYPE}
74+
SIZE
75+
${BM_SIZE}
76+
OUTPUT
77+
${HEADER})
78+
79+
foreach(ALG_NAME ${ALG_NAMES})
80+
if("${ALG_NAME}_${DATASET}" IN_LIST EXCLUDED_COMBINATIONS)
81+
continue()
82+
endif()
83+
84+
set(name "${ALG_NAME}_${DATASET}_bench")
85+
add_benchmark(
86+
${name}
87+
NANO
88+
FILES
89+
pseudo_pext.cpp
90+
SYSTEM_LIBRARIES
91+
cib_lookup
92+
mph
93+
frozen-headers)
94+
target_compile_options(${name} PRIVATE -fconstexpr-steps=4000000000
95+
--include=${HEADER})
96+
target_compile_definitions(
97+
${name} PRIVATE ALG_NAME=bench_${ALG_NAME} DATASET=${DATASET}
98+
ANKERL_NANOBENCH_IMPLEMENT)
99+
add_dependencies(${name} ${DATA_TARGET})
100+
endforeach()
101+
endfunction()
102+
103+
foreach(type IN ITEMS uint16 uint32)
104+
foreach(i RANGE 1 10)
105+
gen_pp_benchmarks(TYPE ${type} SIZE ${i})
106+
endforeach()
107+
foreach(i RANGE 20 100 10)
108+
gen_pp_benchmarks(TYPE ${type} SIZE ${i})
109+
endforeach()
110+
foreach(i RANGE 200 1000 100)
111+
gen_pp_benchmarks(TYPE ${type} SIZE ${i})
112+
endforeach()
113+
endforeach()
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include <cstddef>
4+
#include <memory>
5+
6+
inline std::size_t allocated_size = 0;
7+
8+
template <typename T> class TrackingAllocator {
9+
public:
10+
using value_type = T;
11+
12+
TrackingAllocator() noexcept {}
13+
14+
template <typename U>
15+
TrackingAllocator(TrackingAllocator<U> const &) noexcept {}
16+
17+
template <typename U> struct rebind {
18+
using other = TrackingAllocator<U>;
19+
};
20+
21+
T *allocate(std::size_t n) {
22+
T *ptr = std::allocator<T>{}.allocate(n);
23+
allocated_size += (n * sizeof(T));
24+
return ptr;
25+
}
26+
27+
void deallocate(T *p, std::size_t n) {
28+
std::allocator<T>{}.deallocate(p, n);
29+
allocated_size -= (n * sizeof(T));
30+
}
31+
};
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#pragma once
2+
3+
#include <cstddef>
4+
#include <cstdio>
5+
#include <utility>
6+
7+
#include <frozen/map.h>
8+
#include <nanobench.h>
9+
10+
template <auto data, typename T> constexpr auto make_frozen_map() {
11+
return []<std::size_t... i>(std::index_sequence<i...>) {
12+
return frozen::map<T, T, data.size()>{
13+
{{static_cast<T>(data[i].first),
14+
static_cast<T>(data[i].second)}...}};
15+
}(std::make_index_sequence<data.size()>{});
16+
}
17+
18+
template <auto data, typename T>
19+
__attribute__((noinline, flatten)) T do_frozen_map(T k) {
20+
constexpr static auto map = make_frozen_map<data, T>();
21+
return map.find(k)->second;
22+
}
23+
24+
template <auto data, typename T> void bench_frozen_map(auto name) {
25+
26+
constexpr auto map = make_frozen_map<data, T>();
27+
28+
printf("size: %lu\n", sizeof(map));
29+
30+
do_frozen_map<data, T>(T{});
31+
32+
T k = static_cast<T>(data[0].first);
33+
ankerl::nanobench::Bench().minEpochIterations(2000000).run("chained", [&] {
34+
k = map.find(k)->second;
35+
ankerl::nanobench::doNotOptimizeAway(k);
36+
});
37+
38+
auto i = std::size_t{};
39+
ankerl::nanobench::Bench().minEpochIterations(2000000).run(
40+
"independent", [&] {
41+
auto v = map.find(data[i].first)->second;
42+
i++;
43+
if (i >= data.size()) {
44+
i = 0;
45+
}
46+
ankerl::nanobench::doNotOptimizeAway(v);
47+
});
48+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#pragma once
2+
3+
#include <cstddef>
4+
#include <cstdio>
5+
#include <utility>
6+
7+
#include <frozen/unordered_map.h>
8+
#include <nanobench.h>
9+
10+
template <auto data, typename T> constexpr auto make_frozen_unordered_map() {
11+
return []<std::size_t... i>(std::index_sequence<i...>) {
12+
return frozen::unordered_map<T, T, data.size()>{
13+
{{static_cast<T>(data[i].first),
14+
static_cast<T>(data[i].second)}...}};
15+
}(std::make_index_sequence<data.size()>{});
16+
}
17+
18+
template <auto data, typename T>
19+
__attribute__((noinline, flatten)) T do_frozen_unordered_map(T k) {
20+
constexpr static auto map = make_frozen_unordered_map<data, T>();
21+
return map.find(k)->second;
22+
}
23+
24+
template <auto data, typename T> void bench_frozen_unordered_map(auto name) {
25+
26+
constexpr auto map = make_frozen_unordered_map<data, T>();
27+
28+
printf("size: %lu\n", sizeof(map));
29+
30+
do_frozen_unordered_map<data, T>(T{});
31+
32+
T k = static_cast<T>(data[0].first);
33+
ankerl::nanobench::Bench().minEpochIterations(2000000).run("chained", [&] {
34+
k = map.find(k)->second;
35+
ankerl::nanobench::doNotOptimizeAway(k);
36+
});
37+
38+
auto i = std::size_t{};
39+
ankerl::nanobench::Bench().minEpochIterations(2000000).run(
40+
"independent", [&] {
41+
auto v = map.find(data[i].first)->second;
42+
i++;
43+
if (i >= data.size()) {
44+
i = 0;
45+
}
46+
ankerl::nanobench::doNotOptimizeAway(v);
47+
});
48+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
#include <array>
4+
#include <cstddef>
5+
#include <mph>
6+
#include <utility>
7+
8+
#include <nanobench.h>
9+
10+
template <auto data, typename T> constexpr auto make_mph() {
11+
constexpr static auto input_data =
12+
[]<std::size_t... i>(std::index_sequence<i...>) {
13+
return std::array<mph::pair<T, T>, data.size()>{
14+
{{static_cast<T>(data[i].first),
15+
static_cast<T>(data[i].second)}...}};
16+
}(std::make_index_sequence<data.size()>{});
17+
18+
constexpr auto map = mph::hash<input_data>;
19+
20+
return map;
21+
}
22+
23+
template <auto data, typename T>
24+
__attribute__((noinline, flatten)) T do_mph(T k) {
25+
constexpr static auto map = make_mph<data, T>();
26+
return *map(k);
27+
}
28+
29+
template <auto data, typename T> void bench_mph(auto name) {
30+
31+
constexpr auto map = make_mph<data, T>();
32+
33+
// printf("\nmph\n");
34+
do_mph<data, T>(T{});
35+
36+
T k = static_cast<T>(data[0].first);
37+
ankerl::nanobench::Bench().minEpochIterations(2000000).run("chained", [&] {
38+
k = *map(k);
39+
ankerl::nanobench::doNotOptimizeAway(k);
40+
});
41+
42+
auto i = std::size_t{};
43+
ankerl::nanobench::Bench().minEpochIterations(2000000).run(
44+
"independent", [&] {
45+
auto v = *map(static_cast<T>(data[i].first));
46+
i++;
47+
if (i >= data.size()) {
48+
i = 0;
49+
}
50+
ankerl::nanobench::doNotOptimizeAway(v);
51+
});
52+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#pragma once
2+
3+
#include <array>
4+
#include <cstddef>
5+
#include <mph>
6+
#include <utility>
7+
8+
#include <nanobench.h>
9+
10+
template <auto data, typename T> constexpr auto make_mph_pext() {
11+
constexpr static auto input_data =
12+
[]<std::size_t... i>(std::index_sequence<i...>) {
13+
return std::array<mph::pair<T, T>, data.size()>{
14+
{{static_cast<T>(data[i].first),
15+
static_cast<T>(data[i].second)}...}};
16+
}(std::make_index_sequence<data.size()>{});
17+
18+
constexpr auto conditional_pext_policy =
19+
[]<auto const... ts>(auto &&...args) {
20+
return mph::pext<32u>{}.template operator()<ts...>(
21+
std::forward<decltype(args)>(args)...);
22+
};
23+
24+
constexpr auto map = mph::hash<input_data, conditional_pext_policy>;
25+
26+
return map;
27+
}
28+
29+
template <auto data, typename T>
30+
__attribute__((noinline, flatten)) T do_mph_pext(T k) {
31+
constexpr static auto map = make_mph_pext<data, T>();
32+
return *map(k);
33+
}
34+
35+
template <auto data, typename T> void bench_mph_pext(auto name) {
36+
37+
constexpr auto map = make_mph_pext<data, T>();
38+
39+
// printf("\nmph\n");
40+
do_mph_pext<data, T>(T{});
41+
42+
T k = static_cast<T>(data[0].first);
43+
ankerl::nanobench::Bench().minEpochIterations(2000000).run("chained", [&] {
44+
k = *map(k);
45+
ankerl::nanobench::doNotOptimizeAway(k);
46+
});
47+
48+
auto i = std::size_t{};
49+
ankerl::nanobench::Bench().minEpochIterations(2000000).run(
50+
"independent", [&] {
51+
auto v = *map(static_cast<T>(data[i].first));
52+
i++;
53+
if (i >= data.size()) {
54+
i = 0;
55+
}
56+
ankerl::nanobench::doNotOptimizeAway(v);
57+
});
58+
}

0 commit comments

Comments
 (0)