From 8889837da535b1164d0fc52e8afeb671ad993b32 Mon Sep 17 00:00:00 2001 From: Fabrice Date: Mon, 13 Apr 2026 16:44:23 +0200 Subject: fix file naming --- benches/CMakeLists.txt | 2 +- benches/abseil_bench.cc | 87 +++++++ benches/abseil_bench.cpp | 87 ------- benches/bench_common.h | 544 ++++++++++++++++++++++++++++++++++++++++ benches/bench_common.hpp | 544 ---------------------------------------- benches/cheesemap_bench.cc | 80 ++++++ benches/cheesemap_bench.cpp | 80 ------ benches/klib_bench.cc | 238 ++++++++++++++++++ benches/klib_bench.cpp | 238 ------------------ benches/tidwall_bench.cc | 85 +++++++ benches/tidwall_bench.cpp | 85 ------- benches/unordered_map_bench.cc | 87 +++++++ benches/unordered_map_bench.cpp | 87 ------- 13 files changed, 1122 insertions(+), 1122 deletions(-) create mode 100644 benches/abseil_bench.cc delete mode 100644 benches/abseil_bench.cpp create mode 100644 benches/bench_common.h delete mode 100644 benches/bench_common.hpp create mode 100644 benches/cheesemap_bench.cc delete mode 100644 benches/cheesemap_bench.cpp create mode 100644 benches/klib_bench.cc delete mode 100644 benches/klib_bench.cpp create mode 100644 benches/tidwall_bench.cc delete mode 100644 benches/tidwall_bench.cpp create mode 100644 benches/unordered_map_bench.cc delete mode 100644 benches/unordered_map_bench.cpp (limited to 'benches') diff --git a/benches/CMakeLists.txt b/benches/CMakeLists.txt index c8fdba3..ebee9e8 100644 --- a/benches/CMakeLists.txt +++ b/benches/CMakeLists.txt @@ -17,7 +17,7 @@ set(cm_bench_targets ) foreach(target_name IN LISTS cm_bench_targets) - add_executable(${target_name} "${cm_benchesdir}/${target_name}.cpp") + add_executable(${target_name} "${cm_benchesdir}/${target_name}.cc") target_include_directories(${target_name} PRIVATE diff --git a/benches/abseil_bench.cc b/benches/abseil_bench.cc new file mode 100644 index 0000000..3a43ed4 --- /dev/null +++ b/benches/abseil_bench.cc @@ -0,0 +1,87 @@ +#include + +#include "bench_common.h" + +namespace { + +using namespace cmbench; + +static void BM_Insert_Scalar(benchmark::State& state) { + bench_insert>( + state, scalar_workload(), + {"absl::flat_hash_map", "c++", "Scalar", "Insert"}); +} +static void BM_LookupHit_Scalar(benchmark::State& state) { + bench_lookup_hit>( + state, scalar_workload(), + {"absl::flat_hash_map", "c++", "Scalar", "LookupHit"}); +} +static void BM_LookupMiss_Scalar(benchmark::State& state) { + bench_lookup_miss>( + state, scalar_workload(), + {"absl::flat_hash_map", "c++", "Scalar", "LookupMiss"}); +} +static void BM_Erase_Scalar(benchmark::State& state) { + bench_erase>( + state, scalar_workload(), + {"absl::flat_hash_map", "c++", "Scalar", "Erase"}); +} + +static void BM_Insert_HandlePayload(benchmark::State& state) { + bench_insert>( + state, entity_workload(), + {"absl::flat_hash_map", "c++", "HandlePayload", "Insert"}); +} +static void BM_LookupHit_HandlePayload(benchmark::State& state) { + bench_lookup_hit>( + state, entity_workload(), + {"absl::flat_hash_map", "c++", "HandlePayload", "LookupHit"}); +} +static void BM_LookupMiss_HandlePayload(benchmark::State& state) { + bench_lookup_miss>( + state, entity_workload(), + {"absl::flat_hash_map", "c++", "HandlePayload", "LookupMiss"}); +} +static void BM_Erase_HandlePayload(benchmark::State& state) { + bench_erase>( + state, entity_workload(), + {"absl::flat_hash_map", "c++", "HandlePayload", "Erase"}); +} + +static void BM_Insert_CompositeKey(benchmark::State& state) { + bench_insert>( + state, component_workload(), + {"absl::flat_hash_map", "c++", "CompositeKey", "Insert"}); +} +static void BM_LookupHit_CompositeKey(benchmark::State& state) { + bench_lookup_hit>( + state, component_workload(), + {"absl::flat_hash_map", "c++", "CompositeKey", "LookupHit"}); +} +static void BM_LookupMiss_CompositeKey(benchmark::State& state) { + bench_lookup_miss>( + state, component_workload(), + {"absl::flat_hash_map", "c++", "CompositeKey", "LookupMiss"}); +} +static void BM_Erase_CompositeKey(benchmark::State& state) { + bench_erase>( + state, component_workload(), + {"absl::flat_hash_map", "c++", "CompositeKey", "Erase"}); +} + +} // namespace + +BENCHMARK(BM_Insert_Scalar); +BENCHMARK(BM_LookupHit_Scalar); +BENCHMARK(BM_LookupMiss_Scalar); +BENCHMARK(BM_Erase_Scalar); + +BENCHMARK(BM_Insert_HandlePayload); +BENCHMARK(BM_LookupHit_HandlePayload); +BENCHMARK(BM_LookupMiss_HandlePayload); +BENCHMARK(BM_Erase_HandlePayload); + +BENCHMARK(BM_Insert_CompositeKey); +BENCHMARK(BM_LookupHit_CompositeKey); +BENCHMARK(BM_LookupMiss_CompositeKey); +BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/abseil_bench.cpp b/benches/abseil_bench.cpp deleted file mode 100644 index 813bf51..0000000 --- a/benches/abseil_bench.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include - -#include "bench_common.hpp" - -namespace { - -using namespace cmbench; - -static void BM_Insert_Scalar(benchmark::State& state) { - bench_insert>( - state, scalar_workload(), - {"absl::flat_hash_map", "c++", "Scalar", "Insert"}); -} -static void BM_LookupHit_Scalar(benchmark::State& state) { - bench_lookup_hit>( - state, scalar_workload(), - {"absl::flat_hash_map", "c++", "Scalar", "LookupHit"}); -} -static void BM_LookupMiss_Scalar(benchmark::State& state) { - bench_lookup_miss>( - state, scalar_workload(), - {"absl::flat_hash_map", "c++", "Scalar", "LookupMiss"}); -} -static void BM_Erase_Scalar(benchmark::State& state) { - bench_erase>( - state, scalar_workload(), - {"absl::flat_hash_map", "c++", "Scalar", "Erase"}); -} - -static void BM_Insert_HandlePayload(benchmark::State& state) { - bench_insert>( - state, entity_workload(), - {"absl::flat_hash_map", "c++", "HandlePayload", "Insert"}); -} -static void BM_LookupHit_HandlePayload(benchmark::State& state) { - bench_lookup_hit>( - state, entity_workload(), - {"absl::flat_hash_map", "c++", "HandlePayload", "LookupHit"}); -} -static void BM_LookupMiss_HandlePayload(benchmark::State& state) { - bench_lookup_miss>( - state, entity_workload(), - {"absl::flat_hash_map", "c++", "HandlePayload", "LookupMiss"}); -} -static void BM_Erase_HandlePayload(benchmark::State& state) { - bench_erase>( - state, entity_workload(), - {"absl::flat_hash_map", "c++", "HandlePayload", "Erase"}); -} - -static void BM_Insert_CompositeKey(benchmark::State& state) { - bench_insert>( - state, component_workload(), - {"absl::flat_hash_map", "c++", "CompositeKey", "Insert"}); -} -static void BM_LookupHit_CompositeKey(benchmark::State& state) { - bench_lookup_hit>( - state, component_workload(), - {"absl::flat_hash_map", "c++", "CompositeKey", "LookupHit"}); -} -static void BM_LookupMiss_CompositeKey(benchmark::State& state) { - bench_lookup_miss>( - state, component_workload(), - {"absl::flat_hash_map", "c++", "CompositeKey", "LookupMiss"}); -} -static void BM_Erase_CompositeKey(benchmark::State& state) { - bench_erase>( - state, component_workload(), - {"absl::flat_hash_map", "c++", "CompositeKey", "Erase"}); -} - -} // namespace - -BENCHMARK(BM_Insert_Scalar); -BENCHMARK(BM_LookupHit_Scalar); -BENCHMARK(BM_LookupMiss_Scalar); -BENCHMARK(BM_Erase_Scalar); - -BENCHMARK(BM_Insert_HandlePayload); -BENCHMARK(BM_LookupHit_HandlePayload); -BENCHMARK(BM_LookupMiss_HandlePayload); -BENCHMARK(BM_Erase_HandlePayload); - -BENCHMARK(BM_Insert_CompositeKey); -BENCHMARK(BM_LookupHit_CompositeKey); -BENCHMARK(BM_LookupMiss_CompositeKey); -BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/bench_common.h b/benches/bench_common.h new file mode 100644 index 0000000..1f3b4d3 --- /dev/null +++ b/benches/bench_common.h @@ -0,0 +1,544 @@ +#ifndef CHEESEMAP_BENCH_COMMON_HPP +#define CHEESEMAP_BENCH_COMMON_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cheesemap.h" +#include "tidwall/hashmap.h" +#include "absl/container/flat_hash_map.h" + + +namespace cmbench { + +inline constexpr std::int64_t kEntryCount = 1'000'000; +inline constexpr std::string_view kProtocolVersion = "1"; +inline constexpr std::string_view kDatasetVersion = "1"; +inline constexpr std::string_view kHashQuality = "good"; +inline constexpr std::string_view kHashName = "xxh_avalanche"; + +[[noreturn]] inline void panic_impl(const char* file, cm_u32 line, + const char* fmt, ...) { + std::fprintf(stderr, "panic at %s:%u: ", file, line); + va_list args; + va_start(args, fmt); + std::vfprintf(stderr, fmt, args); + va_end(args); + std::fputc('\n', stderr); + std::abort(); +} + +inline cm_u8* default_alloc(cm_usize size, cm_usize align, cm_u8* user) { + (void)user; + return static_cast(std::aligned_alloc(align, size)); +} + +inline void default_dealloc(cm_u8* ptr, cm_u8* user) { + (void)user; + std::free(ptr); +} + +inline std::uint64_t rotl64(std::uint64_t x, unsigned bits) { + return (x << bits) | (x >> (64 - bits)); +} + +inline std::uint64_t xxh64_avalanche(std::uint64_t x) { + x ^= x >> 33; + x *= 0xc2b2ae3d27d4eb4fULL; + x ^= x >> 29; + x *= 0x165667b19e3779f9ULL; + x ^= x >> 32; + return x; +} + +template +inline std::array as_words(const T& value) { + static_assert(std::is_trivially_copyable_v); + std::array words{}; + std::memcpy(words.data(), &value, sizeof(T)); + return words; +} + +template +inline std::uint64_t hash_xxh_avalanche(const T& value) { + auto words = as_words(value); + std::uint64_t acc = 0x165667b19e3779f9ULL ^ sizeof(T); + for (std::uint64_t word : words) { + acc += word * 0x9e3779b185ebca87ULL; + acc = rotl64(acc, 31); + acc *= 0xc2b2ae3d27d4eb4fULL; + } + return xxh64_avalanche(acc); +} + +template +inline bool byte_equal(const T& lhs, const T& rhs) { + static_assert(std::is_trivially_copyable_v); + return std::memcmp(&lhs, &rhs, sizeof(T)) == 0; +} + +struct ScalarValue { + std::uint64_t value; +}; + +struct EntityId { + std::uint32_t index; + std::uint32_t generation; +}; + +struct ComponentPayload { + float position[3]; + float velocity[3]; + std::uint32_t archetype; + std::uint32_t chunk; +}; + +struct ComponentKey { + std::uint64_t archetype_mask; + std::uint32_t component_id; + std::uint32_t chunk; + std::uint32_t row; + std::uint32_t generation; +}; + +struct ComponentMeta { + std::uint64_t entity_mask; + std::uint32_t dense_index; + std::uint32_t sparse_index; + std::uint64_t version; +}; + +template +struct Workload { + std::vector keys; + std::vector miss_keys; + std::vector values; +}; + +template +inline void shuffle_keys(std::vector& keys, std::mt19937_64& rng) { + std::shuffle(keys.begin(), keys.end(), rng); +} + +inline Workload make_scalar_workload( + std::size_t count) { + Workload workload{ + .keys = std::vector(count), + .miss_keys = std::vector(count), + .values = std::vector(count), + }; + + std::mt19937_64 rng(0xc0ffee5eedULL); + for (std::size_t i = 0; i < count; ++i) { + workload.keys[i] = xxh64_avalanche(i + 1); + workload.miss_keys[i] = xxh64_avalanche(i + 1 + count); + workload.values[i] = + ScalarValue{xxh64_avalanche(i ^ 0x123456789abcdef0ULL)}; + } + shuffle_keys(workload.keys, rng); + shuffle_keys(workload.miss_keys, rng); + return workload; +} + +inline Workload make_entity_workload( + std::size_t count) { + Workload workload{ + .keys = std::vector(count), + .miss_keys = std::vector(count), + .values = std::vector(count), + }; + + std::mt19937_64 rng(0xEC500123ULL); + for (std::size_t i = 0; i < count; ++i) { + workload.keys[i] = EntityId{static_cast(i), + static_cast(i >> 12)}; + workload.miss_keys[i] = EntityId{static_cast(i), + static_cast((i >> 12) + 1)}; + + float base = static_cast(i & 0xffff); + workload.values[i] = ComponentPayload{ + .position = {base + 0.1f, base + 0.2f, base + 0.3f}, + .velocity = {base + 1.1f, base + 1.2f, base + 1.3f}, + .archetype = static_cast(xxh64_avalanche(i) & 0xffff), + .chunk = static_cast(i / 64), + }; + } + shuffle_keys(workload.keys, rng); + shuffle_keys(workload.miss_keys, rng); + return workload; +} + +inline Workload make_component_workload( + std::size_t count) { + Workload workload{ + .keys = std::vector(count), + .miss_keys = std::vector(count), + .values = std::vector(count), + }; + + std::mt19937_64 rng(0xA11CECC5ULL); + for (std::size_t i = 0; i < count; ++i) { + std::uint64_t archetype = xxh64_avalanche(i * 0x9e3779b97f4a7c15ULL); + workload.keys[i] = ComponentKey{ + .archetype_mask = archetype, + .component_id = static_cast((i * 17) & 0xffff), + .chunk = static_cast(i / 64), + .row = static_cast(i % 64), + .generation = static_cast(i >> 10), + }; + workload.miss_keys[i] = ComponentKey{ + .archetype_mask = archetype ^ 0xfeedfacecafebeefULL, + .component_id = static_cast((i * 17) & 0xffff), + .chunk = static_cast(i / 64), + .row = static_cast(i % 64), + .generation = static_cast(i >> 10), + }; + workload.values[i] = ComponentMeta{ + .entity_mask = xxh64_avalanche(i + 7), + .dense_index = static_cast(i), + .sparse_index = + static_cast(xxh64_avalanche(i) & 0xffffffffU), + .version = xxh64_avalanche(i ^ 0xabcdef01ULL), + }; + } + shuffle_keys(workload.keys, rng); + shuffle_keys(workload.miss_keys, rng); + return workload; +} + +inline const Workload& scalar_workload() { + static const auto workload = make_scalar_workload(kEntryCount); + return workload; +} + +inline const Workload& entity_workload() { + static const auto workload = make_entity_workload(kEntryCount); + return workload; +} + +inline const Workload& component_workload() { + static const auto workload = make_component_workload(kEntryCount); + return workload; +} + +template +inline cm_hash_t cheesemap_hash_adapter(const cm_u8* key, cm_u8* user) { + (void)user; + return hash_xxh_avalanche(*reinterpret_cast(key)); +} + +template +inline bool cheesemap_equal_adapter(const cm_u8* lhs, const cm_u8* rhs, + cm_u8* user) { + (void)user; + return byte_equal(*reinterpret_cast(lhs), + *reinterpret_cast(rhs)); +} + +struct Meta { + std::string_view implementation; + std::string_view language; + std::string_view dataset; + std::string_view workload_category; +}; + +inline void set_common_metadata(benchmark::State& state, const Meta& meta) { + std::string label; + label.reserve(128); + label.append("implementation="); + label.append(meta.implementation); + label.append(",language="); + label.append(meta.language); + label.append(",dataset="); + label.append(meta.dataset); + label.append(",workload="); + label.append(meta.workload_category); + label.append(",hash_quality="); + label.append(kHashQuality); + label.append(",hash="); + label.append(kHashName); + label.append(",protocol="); + label.append(kProtocolVersion); + label.append(",dataset_version="); + label.append(kDatasetVersion); + state.SetLabel(label); + state.counters["entry_count"] = + benchmark::Counter(static_cast(kEntryCount)); +} + +template +struct CheesemapAdapter { + cheesemap map; + + CheesemapAdapter() { + cm_init(&map, sizeof(Key), alignof(Key), sizeof(Value), alignof(Value), + nullptr, cheesemap_hash_adapter, cheesemap_equal_adapter, + default_alloc, default_dealloc); + } + + ~CheesemapAdapter() { cm_drop(&map); } + + CheesemapAdapter(const CheesemapAdapter&) = delete; + CheesemapAdapter& operator=(const CheesemapAdapter&) = delete; + + void reserve(std::size_t count) { + if (!cm_reserve(&map, count)) + panic_impl(__FILE__, __LINE__, "reserve failed"); + } + + void insert(const Key& key, const Value& value) { + if (!cm_insert(&map, reinterpret_cast(&key), + reinterpret_cast(&value))) { + panic_impl(__FILE__, __LINE__, "insert failed"); + } + } + + Value* lookup_hit(const Key& key) { + cm_u8* value_ptr = nullptr; + if (!cm_lookup(&map, reinterpret_cast(&key), &value_ptr)) + panic_impl(__FILE__, __LINE__, "lookup hit failed"); + return reinterpret_cast(value_ptr); + } + + void lookup_miss(const Key& key) { + cm_u8* value_ptr = nullptr; + if (cm_lookup(&map, reinterpret_cast(&key), &value_ptr)) + panic_impl(__FILE__, __LINE__, "lookup miss failed"); + benchmark::DoNotOptimize(value_ptr); + } + + void erase(const Key& key) { + if (!cm_remove(&map, reinterpret_cast(&key), nullptr)) + panic_impl(__FILE__, __LINE__, "erase failed"); + } +}; + +template +struct UnorderedHashAdapter { + std::size_t operator()(const Key& key) const noexcept { + return static_cast(hash_xxh_avalanche(key)); + } +}; + +template +struct UnorderedEqualAdapter { + bool operator()(const Key& lhs, const Key& rhs) const noexcept { + return byte_equal(lhs, rhs); + } +}; + +template +struct UnorderedMapAdapter { + using Map = std::unordered_map, + UnorderedEqualAdapter>; + + Map map; + + void reserve(std::size_t count) { map.reserve(count); } + + void insert(const Key& key, const Value& value) { + map.insert_or_assign(key, value); + } + + Value* lookup_hit(const Key& key) { + auto it = map.find(key); + if (it == map.end()) panic_impl(__FILE__, __LINE__, "lookup hit failed"); + return &it->second; + } + + void lookup_miss(const Key& key) { + auto it = map.find(key); + if (it != map.end()) panic_impl(__FILE__, __LINE__, "lookup miss failed"); + benchmark::DoNotOptimize(it); + } + + void erase(const Key& key) { + if (map.erase(key) != 1) panic_impl(__FILE__, __LINE__, "erase failed"); + } +}; + +template +struct TidwallEntry { + Key key; + Value value; +}; + +template +struct TidwallAdapter { + using Entry = TidwallEntry; + + hashmap* map = nullptr; + + static std::uint64_t hash_entry(const void* item, std::uint64_t seed0, + std::uint64_t seed1) { + (void)seed0; + (void)seed1; + const auto* entry = static_cast(item); + return hash_xxh_avalanche(entry->key); + } + + static int compare_entry(const void* lhs, const void* rhs, void* udata) { + (void)udata; + const auto* left = static_cast(lhs); + const auto* right = static_cast(rhs); + return byte_equal(left->key, right->key) ? 0 : 1; + } + + TidwallAdapter() { + map = hashmap_new(sizeof(Entry), static_cast(kEntryCount), 0, + 0, hash_entry, compare_entry, nullptr, nullptr); + if (map == nullptr) panic_impl(__FILE__, __LINE__, "hashmap_new failed"); + } + + ~TidwallAdapter() { + if (map != nullptr) hashmap_free(map); + } + + TidwallAdapter(const TidwallAdapter&) = delete; + TidwallAdapter& operator=(const TidwallAdapter&) = delete; + + void reserve(std::size_t count) { benchmark::DoNotOptimize(count); } + + void insert(const Key& key, const Value& value) { + const Entry entry{key, value}; + if (hashmap_set(map, &entry) == nullptr && hashmap_oom(map)) + panic_impl(__FILE__, __LINE__, "insert failed"); + } + + Value* lookup_hit(const Key& key) { + const Entry query{key, Value{}}; + auto* found = static_cast(hashmap_get(map, &query)); + if (found == nullptr) panic_impl(__FILE__, __LINE__, "lookup hit failed"); + return const_cast(&found->value); + } + + void lookup_miss(const Key& key) { + const Entry query{key, Value{}}; + auto* found = static_cast(hashmap_get(map, &query)); + if (found != nullptr) panic_impl(__FILE__, __LINE__, "lookup miss failed"); + benchmark::DoNotOptimize(found); + } + + void erase(const Key& key) { + const Entry query{key, Value{}}; + if (hashmap_delete(map, &query) == nullptr) + panic_impl(__FILE__, __LINE__, "erase failed"); + } +}; + +template +struct AbseilAdapter { + using Map = absl::flat_hash_map, + UnorderedEqualAdapter>; + + Map map; + + void reserve(std::size_t count) { map.reserve(count); } + + void insert(const Key& key, const Value& value) { + map.insert_or_assign(key, value); + } + + Value* lookup_hit(const Key& key) { + auto it = map.find(key); + if (it == map.end()) panic_impl(__FILE__, __LINE__, "lookup hit failed"); + return &it->second; + } + + void lookup_miss(const Key& key) { + auto it = map.find(key); + if (it != map.end()) panic_impl(__FILE__, __LINE__, "lookup miss failed"); + benchmark::DoNotOptimize(it); + } + + void erase(const Key& key) { + if (map.erase(key) != 1) panic_impl(__FILE__, __LINE__, "erase failed"); + } +}; + +template +inline void fill_container(Adapter& adapter, + const Workload& workload) { + adapter.reserve(workload.keys.size()); + for (std::size_t i = 0; i < workload.keys.size(); ++i) + adapter.insert(workload.keys[i], workload.values[i]); +} + +template +inline void bench_insert(benchmark::State& state, + const Workload& workload, + const Meta& meta) { + set_common_metadata(state, meta); + for (auto _ : state) { + Adapter adapter; + fill_container(adapter, workload); + benchmark::ClobberMemory(); + } +} + +template +inline void bench_lookup_hit(benchmark::State& state, + const Workload& workload, + const Meta& meta) { + set_common_metadata(state, meta); + for (auto _ : state) { + state.PauseTiming(); + Adapter adapter; + fill_container(adapter, workload); + state.ResumeTiming(); + + for (const Key& key : workload.keys) { + Value* value_ptr = adapter.lookup_hit(key); + benchmark::DoNotOptimize(value_ptr); + } + benchmark::ClobberMemory(); + } +} + +template +inline void bench_lookup_miss(benchmark::State& state, + const Workload& workload, + const Meta& meta) { + set_common_metadata(state, meta); + for (auto _ : state) { + state.PauseTiming(); + Adapter adapter; + fill_container(adapter, workload); + state.ResumeTiming(); + + for (const Key& key : workload.miss_keys) adapter.lookup_miss(key); + benchmark::ClobberMemory(); + } +} + +template +inline void bench_erase(benchmark::State& state, + const Workload& workload, + const Meta& meta) { + set_common_metadata(state, meta); + for (auto _ : state) { + state.PauseTiming(); + Adapter adapter; + fill_container(adapter, workload); + state.ResumeTiming(); + + for (const Key& key : workload.keys) adapter.erase(key); + benchmark::ClobberMemory(); + } +} + +} // namespace cmbench + +#endif diff --git a/benches/bench_common.hpp b/benches/bench_common.hpp deleted file mode 100644 index 1f3b4d3..0000000 --- a/benches/bench_common.hpp +++ /dev/null @@ -1,544 +0,0 @@ -#ifndef CHEESEMAP_BENCH_COMMON_HPP -#define CHEESEMAP_BENCH_COMMON_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cheesemap.h" -#include "tidwall/hashmap.h" -#include "absl/container/flat_hash_map.h" - - -namespace cmbench { - -inline constexpr std::int64_t kEntryCount = 1'000'000; -inline constexpr std::string_view kProtocolVersion = "1"; -inline constexpr std::string_view kDatasetVersion = "1"; -inline constexpr std::string_view kHashQuality = "good"; -inline constexpr std::string_view kHashName = "xxh_avalanche"; - -[[noreturn]] inline void panic_impl(const char* file, cm_u32 line, - const char* fmt, ...) { - std::fprintf(stderr, "panic at %s:%u: ", file, line); - va_list args; - va_start(args, fmt); - std::vfprintf(stderr, fmt, args); - va_end(args); - std::fputc('\n', stderr); - std::abort(); -} - -inline cm_u8* default_alloc(cm_usize size, cm_usize align, cm_u8* user) { - (void)user; - return static_cast(std::aligned_alloc(align, size)); -} - -inline void default_dealloc(cm_u8* ptr, cm_u8* user) { - (void)user; - std::free(ptr); -} - -inline std::uint64_t rotl64(std::uint64_t x, unsigned bits) { - return (x << bits) | (x >> (64 - bits)); -} - -inline std::uint64_t xxh64_avalanche(std::uint64_t x) { - x ^= x >> 33; - x *= 0xc2b2ae3d27d4eb4fULL; - x ^= x >> 29; - x *= 0x165667b19e3779f9ULL; - x ^= x >> 32; - return x; -} - -template -inline std::array as_words(const T& value) { - static_assert(std::is_trivially_copyable_v); - std::array words{}; - std::memcpy(words.data(), &value, sizeof(T)); - return words; -} - -template -inline std::uint64_t hash_xxh_avalanche(const T& value) { - auto words = as_words(value); - std::uint64_t acc = 0x165667b19e3779f9ULL ^ sizeof(T); - for (std::uint64_t word : words) { - acc += word * 0x9e3779b185ebca87ULL; - acc = rotl64(acc, 31); - acc *= 0xc2b2ae3d27d4eb4fULL; - } - return xxh64_avalanche(acc); -} - -template -inline bool byte_equal(const T& lhs, const T& rhs) { - static_assert(std::is_trivially_copyable_v); - return std::memcmp(&lhs, &rhs, sizeof(T)) == 0; -} - -struct ScalarValue { - std::uint64_t value; -}; - -struct EntityId { - std::uint32_t index; - std::uint32_t generation; -}; - -struct ComponentPayload { - float position[3]; - float velocity[3]; - std::uint32_t archetype; - std::uint32_t chunk; -}; - -struct ComponentKey { - std::uint64_t archetype_mask; - std::uint32_t component_id; - std::uint32_t chunk; - std::uint32_t row; - std::uint32_t generation; -}; - -struct ComponentMeta { - std::uint64_t entity_mask; - std::uint32_t dense_index; - std::uint32_t sparse_index; - std::uint64_t version; -}; - -template -struct Workload { - std::vector keys; - std::vector miss_keys; - std::vector values; -}; - -template -inline void shuffle_keys(std::vector& keys, std::mt19937_64& rng) { - std::shuffle(keys.begin(), keys.end(), rng); -} - -inline Workload make_scalar_workload( - std::size_t count) { - Workload workload{ - .keys = std::vector(count), - .miss_keys = std::vector(count), - .values = std::vector(count), - }; - - std::mt19937_64 rng(0xc0ffee5eedULL); - for (std::size_t i = 0; i < count; ++i) { - workload.keys[i] = xxh64_avalanche(i + 1); - workload.miss_keys[i] = xxh64_avalanche(i + 1 + count); - workload.values[i] = - ScalarValue{xxh64_avalanche(i ^ 0x123456789abcdef0ULL)}; - } - shuffle_keys(workload.keys, rng); - shuffle_keys(workload.miss_keys, rng); - return workload; -} - -inline Workload make_entity_workload( - std::size_t count) { - Workload workload{ - .keys = std::vector(count), - .miss_keys = std::vector(count), - .values = std::vector(count), - }; - - std::mt19937_64 rng(0xEC500123ULL); - for (std::size_t i = 0; i < count; ++i) { - workload.keys[i] = EntityId{static_cast(i), - static_cast(i >> 12)}; - workload.miss_keys[i] = EntityId{static_cast(i), - static_cast((i >> 12) + 1)}; - - float base = static_cast(i & 0xffff); - workload.values[i] = ComponentPayload{ - .position = {base + 0.1f, base + 0.2f, base + 0.3f}, - .velocity = {base + 1.1f, base + 1.2f, base + 1.3f}, - .archetype = static_cast(xxh64_avalanche(i) & 0xffff), - .chunk = static_cast(i / 64), - }; - } - shuffle_keys(workload.keys, rng); - shuffle_keys(workload.miss_keys, rng); - return workload; -} - -inline Workload make_component_workload( - std::size_t count) { - Workload workload{ - .keys = std::vector(count), - .miss_keys = std::vector(count), - .values = std::vector(count), - }; - - std::mt19937_64 rng(0xA11CECC5ULL); - for (std::size_t i = 0; i < count; ++i) { - std::uint64_t archetype = xxh64_avalanche(i * 0x9e3779b97f4a7c15ULL); - workload.keys[i] = ComponentKey{ - .archetype_mask = archetype, - .component_id = static_cast((i * 17) & 0xffff), - .chunk = static_cast(i / 64), - .row = static_cast(i % 64), - .generation = static_cast(i >> 10), - }; - workload.miss_keys[i] = ComponentKey{ - .archetype_mask = archetype ^ 0xfeedfacecafebeefULL, - .component_id = static_cast((i * 17) & 0xffff), - .chunk = static_cast(i / 64), - .row = static_cast(i % 64), - .generation = static_cast(i >> 10), - }; - workload.values[i] = ComponentMeta{ - .entity_mask = xxh64_avalanche(i + 7), - .dense_index = static_cast(i), - .sparse_index = - static_cast(xxh64_avalanche(i) & 0xffffffffU), - .version = xxh64_avalanche(i ^ 0xabcdef01ULL), - }; - } - shuffle_keys(workload.keys, rng); - shuffle_keys(workload.miss_keys, rng); - return workload; -} - -inline const Workload& scalar_workload() { - static const auto workload = make_scalar_workload(kEntryCount); - return workload; -} - -inline const Workload& entity_workload() { - static const auto workload = make_entity_workload(kEntryCount); - return workload; -} - -inline const Workload& component_workload() { - static const auto workload = make_component_workload(kEntryCount); - return workload; -} - -template -inline cm_hash_t cheesemap_hash_adapter(const cm_u8* key, cm_u8* user) { - (void)user; - return hash_xxh_avalanche(*reinterpret_cast(key)); -} - -template -inline bool cheesemap_equal_adapter(const cm_u8* lhs, const cm_u8* rhs, - cm_u8* user) { - (void)user; - return byte_equal(*reinterpret_cast(lhs), - *reinterpret_cast(rhs)); -} - -struct Meta { - std::string_view implementation; - std::string_view language; - std::string_view dataset; - std::string_view workload_category; -}; - -inline void set_common_metadata(benchmark::State& state, const Meta& meta) { - std::string label; - label.reserve(128); - label.append("implementation="); - label.append(meta.implementation); - label.append(",language="); - label.append(meta.language); - label.append(",dataset="); - label.append(meta.dataset); - label.append(",workload="); - label.append(meta.workload_category); - label.append(",hash_quality="); - label.append(kHashQuality); - label.append(",hash="); - label.append(kHashName); - label.append(",protocol="); - label.append(kProtocolVersion); - label.append(",dataset_version="); - label.append(kDatasetVersion); - state.SetLabel(label); - state.counters["entry_count"] = - benchmark::Counter(static_cast(kEntryCount)); -} - -template -struct CheesemapAdapter { - cheesemap map; - - CheesemapAdapter() { - cm_init(&map, sizeof(Key), alignof(Key), sizeof(Value), alignof(Value), - nullptr, cheesemap_hash_adapter, cheesemap_equal_adapter, - default_alloc, default_dealloc); - } - - ~CheesemapAdapter() { cm_drop(&map); } - - CheesemapAdapter(const CheesemapAdapter&) = delete; - CheesemapAdapter& operator=(const CheesemapAdapter&) = delete; - - void reserve(std::size_t count) { - if (!cm_reserve(&map, count)) - panic_impl(__FILE__, __LINE__, "reserve failed"); - } - - void insert(const Key& key, const Value& value) { - if (!cm_insert(&map, reinterpret_cast(&key), - reinterpret_cast(&value))) { - panic_impl(__FILE__, __LINE__, "insert failed"); - } - } - - Value* lookup_hit(const Key& key) { - cm_u8* value_ptr = nullptr; - if (!cm_lookup(&map, reinterpret_cast(&key), &value_ptr)) - panic_impl(__FILE__, __LINE__, "lookup hit failed"); - return reinterpret_cast(value_ptr); - } - - void lookup_miss(const Key& key) { - cm_u8* value_ptr = nullptr; - if (cm_lookup(&map, reinterpret_cast(&key), &value_ptr)) - panic_impl(__FILE__, __LINE__, "lookup miss failed"); - benchmark::DoNotOptimize(value_ptr); - } - - void erase(const Key& key) { - if (!cm_remove(&map, reinterpret_cast(&key), nullptr)) - panic_impl(__FILE__, __LINE__, "erase failed"); - } -}; - -template -struct UnorderedHashAdapter { - std::size_t operator()(const Key& key) const noexcept { - return static_cast(hash_xxh_avalanche(key)); - } -}; - -template -struct UnorderedEqualAdapter { - bool operator()(const Key& lhs, const Key& rhs) const noexcept { - return byte_equal(lhs, rhs); - } -}; - -template -struct UnorderedMapAdapter { - using Map = std::unordered_map, - UnorderedEqualAdapter>; - - Map map; - - void reserve(std::size_t count) { map.reserve(count); } - - void insert(const Key& key, const Value& value) { - map.insert_or_assign(key, value); - } - - Value* lookup_hit(const Key& key) { - auto it = map.find(key); - if (it == map.end()) panic_impl(__FILE__, __LINE__, "lookup hit failed"); - return &it->second; - } - - void lookup_miss(const Key& key) { - auto it = map.find(key); - if (it != map.end()) panic_impl(__FILE__, __LINE__, "lookup miss failed"); - benchmark::DoNotOptimize(it); - } - - void erase(const Key& key) { - if (map.erase(key) != 1) panic_impl(__FILE__, __LINE__, "erase failed"); - } -}; - -template -struct TidwallEntry { - Key key; - Value value; -}; - -template -struct TidwallAdapter { - using Entry = TidwallEntry; - - hashmap* map = nullptr; - - static std::uint64_t hash_entry(const void* item, std::uint64_t seed0, - std::uint64_t seed1) { - (void)seed0; - (void)seed1; - const auto* entry = static_cast(item); - return hash_xxh_avalanche(entry->key); - } - - static int compare_entry(const void* lhs, const void* rhs, void* udata) { - (void)udata; - const auto* left = static_cast(lhs); - const auto* right = static_cast(rhs); - return byte_equal(left->key, right->key) ? 0 : 1; - } - - TidwallAdapter() { - map = hashmap_new(sizeof(Entry), static_cast(kEntryCount), 0, - 0, hash_entry, compare_entry, nullptr, nullptr); - if (map == nullptr) panic_impl(__FILE__, __LINE__, "hashmap_new failed"); - } - - ~TidwallAdapter() { - if (map != nullptr) hashmap_free(map); - } - - TidwallAdapter(const TidwallAdapter&) = delete; - TidwallAdapter& operator=(const TidwallAdapter&) = delete; - - void reserve(std::size_t count) { benchmark::DoNotOptimize(count); } - - void insert(const Key& key, const Value& value) { - const Entry entry{key, value}; - if (hashmap_set(map, &entry) == nullptr && hashmap_oom(map)) - panic_impl(__FILE__, __LINE__, "insert failed"); - } - - Value* lookup_hit(const Key& key) { - const Entry query{key, Value{}}; - auto* found = static_cast(hashmap_get(map, &query)); - if (found == nullptr) panic_impl(__FILE__, __LINE__, "lookup hit failed"); - return const_cast(&found->value); - } - - void lookup_miss(const Key& key) { - const Entry query{key, Value{}}; - auto* found = static_cast(hashmap_get(map, &query)); - if (found != nullptr) panic_impl(__FILE__, __LINE__, "lookup miss failed"); - benchmark::DoNotOptimize(found); - } - - void erase(const Key& key) { - const Entry query{key, Value{}}; - if (hashmap_delete(map, &query) == nullptr) - panic_impl(__FILE__, __LINE__, "erase failed"); - } -}; - -template -struct AbseilAdapter { - using Map = absl::flat_hash_map, - UnorderedEqualAdapter>; - - Map map; - - void reserve(std::size_t count) { map.reserve(count); } - - void insert(const Key& key, const Value& value) { - map.insert_or_assign(key, value); - } - - Value* lookup_hit(const Key& key) { - auto it = map.find(key); - if (it == map.end()) panic_impl(__FILE__, __LINE__, "lookup hit failed"); - return &it->second; - } - - void lookup_miss(const Key& key) { - auto it = map.find(key); - if (it != map.end()) panic_impl(__FILE__, __LINE__, "lookup miss failed"); - benchmark::DoNotOptimize(it); - } - - void erase(const Key& key) { - if (map.erase(key) != 1) panic_impl(__FILE__, __LINE__, "erase failed"); - } -}; - -template -inline void fill_container(Adapter& adapter, - const Workload& workload) { - adapter.reserve(workload.keys.size()); - for (std::size_t i = 0; i < workload.keys.size(); ++i) - adapter.insert(workload.keys[i], workload.values[i]); -} - -template -inline void bench_insert(benchmark::State& state, - const Workload& workload, - const Meta& meta) { - set_common_metadata(state, meta); - for (auto _ : state) { - Adapter adapter; - fill_container(adapter, workload); - benchmark::ClobberMemory(); - } -} - -template -inline void bench_lookup_hit(benchmark::State& state, - const Workload& workload, - const Meta& meta) { - set_common_metadata(state, meta); - for (auto _ : state) { - state.PauseTiming(); - Adapter adapter; - fill_container(adapter, workload); - state.ResumeTiming(); - - for (const Key& key : workload.keys) { - Value* value_ptr = adapter.lookup_hit(key); - benchmark::DoNotOptimize(value_ptr); - } - benchmark::ClobberMemory(); - } -} - -template -inline void bench_lookup_miss(benchmark::State& state, - const Workload& workload, - const Meta& meta) { - set_common_metadata(state, meta); - for (auto _ : state) { - state.PauseTiming(); - Adapter adapter; - fill_container(adapter, workload); - state.ResumeTiming(); - - for (const Key& key : workload.miss_keys) adapter.lookup_miss(key); - benchmark::ClobberMemory(); - } -} - -template -inline void bench_erase(benchmark::State& state, - const Workload& workload, - const Meta& meta) { - set_common_metadata(state, meta); - for (auto _ : state) { - state.PauseTiming(); - Adapter adapter; - fill_container(adapter, workload); - state.ResumeTiming(); - - for (const Key& key : workload.keys) adapter.erase(key); - benchmark::ClobberMemory(); - } -} - -} // namespace cmbench - -#endif diff --git a/benches/cheesemap_bench.cc b/benches/cheesemap_bench.cc new file mode 100644 index 0000000..46960e1 --- /dev/null +++ b/benches/cheesemap_bench.cc @@ -0,0 +1,80 @@ +#include + +#include "bench_common.h" + +namespace { + +using namespace cmbench; + +static void BM_Insert_Scalar(benchmark::State& state) { + bench_insert>( + state, scalar_workload(), {"cheesemap", "c", "Scalar", "Insert"}); +} +static void BM_LookupHit_Scalar(benchmark::State& state) { + bench_lookup_hit>( + state, scalar_workload(), {"cheesemap", "c", "Scalar", "LookupHit"}); +} +static void BM_LookupMiss_Scalar(benchmark::State& state) { + bench_lookup_miss>( + state, scalar_workload(), {"cheesemap", "c", "Scalar", "LookupMiss"}); +} +static void BM_Erase_Scalar(benchmark::State& state) { + bench_erase>( + state, scalar_workload(), {"cheesemap", "c", "Scalar", "Erase"}); +} + +static void BM_Insert_HandlePayload(benchmark::State& state) { + bench_insert>( + state, entity_workload(), {"cheesemap", "c", "HandlePayload", "Insert"}); +} +static void BM_LookupHit_HandlePayload(benchmark::State& state) { + bench_lookup_hit>( + state, entity_workload(), + {"cheesemap", "c", "HandlePayload", "LookupHit"}); +} +static void BM_LookupMiss_HandlePayload(benchmark::State& state) { + bench_lookup_miss>( + state, entity_workload(), + {"cheesemap", "c", "HandlePayload", "LookupMiss"}); +} +static void BM_Erase_HandlePayload(benchmark::State& state) { + bench_erase>( + state, entity_workload(), {"cheesemap", "c", "HandlePayload", "Erase"}); +} + +static void BM_Insert_CompositeKey(benchmark::State& state) { + bench_insert>( + state, component_workload(), + {"cheesemap", "c", "CompositeKey", "Insert"}); +} +static void BM_LookupHit_CompositeKey(benchmark::State& state) { + bench_lookup_hit>( + state, component_workload(), + {"cheesemap", "c", "CompositeKey", "LookupHit"}); +} +static void BM_LookupMiss_CompositeKey(benchmark::State& state) { + bench_lookup_miss>( + state, component_workload(), + {"cheesemap", "c", "CompositeKey", "LookupMiss"}); +} +static void BM_Erase_CompositeKey(benchmark::State& state) { + bench_erase>( + state, component_workload(), {"cheesemap", "c", "CompositeKey", "Erase"}); +} + +} // namespace + +BENCHMARK(BM_Insert_Scalar); +BENCHMARK(BM_LookupHit_Scalar); +BENCHMARK(BM_LookupMiss_Scalar); +BENCHMARK(BM_Erase_Scalar); + +BENCHMARK(BM_Insert_HandlePayload); +BENCHMARK(BM_LookupHit_HandlePayload); +BENCHMARK(BM_LookupMiss_HandlePayload); +BENCHMARK(BM_Erase_HandlePayload); + +BENCHMARK(BM_Insert_CompositeKey); +BENCHMARK(BM_LookupHit_CompositeKey); +BENCHMARK(BM_LookupMiss_CompositeKey); +BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/cheesemap_bench.cpp b/benches/cheesemap_bench.cpp deleted file mode 100644 index a85e54f..0000000 --- a/benches/cheesemap_bench.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include - -#include "bench_common.hpp" - -namespace { - -using namespace cmbench; - -static void BM_Insert_Scalar(benchmark::State& state) { - bench_insert>( - state, scalar_workload(), {"cheesemap", "c", "Scalar", "Insert"}); -} -static void BM_LookupHit_Scalar(benchmark::State& state) { - bench_lookup_hit>( - state, scalar_workload(), {"cheesemap", "c", "Scalar", "LookupHit"}); -} -static void BM_LookupMiss_Scalar(benchmark::State& state) { - bench_lookup_miss>( - state, scalar_workload(), {"cheesemap", "c", "Scalar", "LookupMiss"}); -} -static void BM_Erase_Scalar(benchmark::State& state) { - bench_erase>( - state, scalar_workload(), {"cheesemap", "c", "Scalar", "Erase"}); -} - -static void BM_Insert_HandlePayload(benchmark::State& state) { - bench_insert>( - state, entity_workload(), {"cheesemap", "c", "HandlePayload", "Insert"}); -} -static void BM_LookupHit_HandlePayload(benchmark::State& state) { - bench_lookup_hit>( - state, entity_workload(), - {"cheesemap", "c", "HandlePayload", "LookupHit"}); -} -static void BM_LookupMiss_HandlePayload(benchmark::State& state) { - bench_lookup_miss>( - state, entity_workload(), - {"cheesemap", "c", "HandlePayload", "LookupMiss"}); -} -static void BM_Erase_HandlePayload(benchmark::State& state) { - bench_erase>( - state, entity_workload(), {"cheesemap", "c", "HandlePayload", "Erase"}); -} - -static void BM_Insert_CompositeKey(benchmark::State& state) { - bench_insert>( - state, component_workload(), - {"cheesemap", "c", "CompositeKey", "Insert"}); -} -static void BM_LookupHit_CompositeKey(benchmark::State& state) { - bench_lookup_hit>( - state, component_workload(), - {"cheesemap", "c", "CompositeKey", "LookupHit"}); -} -static void BM_LookupMiss_CompositeKey(benchmark::State& state) { - bench_lookup_miss>( - state, component_workload(), - {"cheesemap", "c", "CompositeKey", "LookupMiss"}); -} -static void BM_Erase_CompositeKey(benchmark::State& state) { - bench_erase>( - state, component_workload(), {"cheesemap", "c", "CompositeKey", "Erase"}); -} - -} // namespace - -BENCHMARK(BM_Insert_Scalar); -BENCHMARK(BM_LookupHit_Scalar); -BENCHMARK(BM_LookupMiss_Scalar); -BENCHMARK(BM_Erase_Scalar); - -BENCHMARK(BM_Insert_HandlePayload); -BENCHMARK(BM_LookupHit_HandlePayload); -BENCHMARK(BM_LookupMiss_HandlePayload); -BENCHMARK(BM_Erase_HandlePayload); - -BENCHMARK(BM_Insert_CompositeKey); -BENCHMARK(BM_LookupHit_CompositeKey); -BENCHMARK(BM_LookupMiss_CompositeKey); -BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/klib_bench.cc b/benches/klib_bench.cc new file mode 100644 index 0000000..d33e0f9 --- /dev/null +++ b/benches/klib_bench.cc @@ -0,0 +1,238 @@ +#include + +#include "bench_common.h" + +extern "C" { +#include "klib/khash.h" +} + +namespace { + +using namespace cmbench; + +// Define khash instances for each key-value type +static inline std::uint64_t kh_hash_u64(std::uint64_t key) { + return hash_xxh_avalanche(key); +} + +static inline int kh_equal_u64(std::uint64_t a, std::uint64_t b) { + return a == b; +} + +KHASH_INIT(u64_scalar, std::uint64_t, ScalarValue, 1, kh_hash_u64, kh_equal_u64) + +static inline std::uint64_t kh_hash_entity(EntityId key) { + return hash_xxh_avalanche(key); +} + +static inline int kh_equal_entity(EntityId a, EntityId b) { + return byte_equal(a, b); +} + +KHASH_INIT(entity_payload, EntityId, ComponentPayload, 1, kh_hash_entity, + kh_equal_entity) + +static inline std::uint64_t kh_hash_component(ComponentKey key) { + return hash_xxh_avalanche(key); +} + +static inline int kh_equal_component(ComponentKey a, ComponentKey b) { + return byte_equal(a, b); +} + +KHASH_INIT(component_meta, ComponentKey, ComponentMeta, 1, kh_hash_component, + kh_equal_component) + +// Adapter for u64 -> ScalarValue +struct KlibScalarAdapter { + khash_t(u64_scalar) * map = nullptr; + + KlibScalarAdapter() { map = kh_init(u64_scalar); } + + ~KlibScalarAdapter() { + if (map != nullptr) kh_destroy(u64_scalar, map); + } + + KlibScalarAdapter(const KlibScalarAdapter&) = delete; + KlibScalarAdapter& operator=(const KlibScalarAdapter&) = delete; + + void reserve(std::size_t count) { benchmark::DoNotOptimize(count); } + + void insert(const std::uint64_t& key, const ScalarValue& value) { + int ret; + khiter_t k = kh_put(u64_scalar, map, key, &ret); + if (ret < 0) panic_impl(__FILE__, __LINE__, "insert failed"); + kh_value(map, k) = value; + } + + ScalarValue* lookup_hit(const std::uint64_t& key) { + khiter_t k = kh_get(u64_scalar, map, key); + if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup hit failed"); + return &kh_value(map, k); + } + + void lookup_miss(const std::uint64_t& key) { + khiter_t k = kh_get(u64_scalar, map, key); + if (k != kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup miss failed"); + benchmark::DoNotOptimize(k); + } + + void erase(const std::uint64_t& key) { + khiter_t k = kh_get(u64_scalar, map, key); + if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "erase failed"); + kh_del(u64_scalar, map, k); + } +}; + +// Adapter for EntityId -> ComponentPayload +struct KlibEntityAdapter { + khash_t(entity_payload) * map = nullptr; + + KlibEntityAdapter() { map = kh_init(entity_payload); } + + ~KlibEntityAdapter() { + if (map != nullptr) kh_destroy(entity_payload, map); + } + + KlibEntityAdapter(const KlibEntityAdapter&) = delete; + KlibEntityAdapter& operator=(const KlibEntityAdapter&) = delete; + + void reserve(std::size_t count) { benchmark::DoNotOptimize(count); } + + void insert(const EntityId& key, const ComponentPayload& value) { + int ret; + khiter_t k = kh_put(entity_payload, map, key, &ret); + if (ret < 0) panic_impl(__FILE__, __LINE__, "insert failed"); + kh_value(map, k) = value; + } + + ComponentPayload* lookup_hit(const EntityId& key) { + khiter_t k = kh_get(entity_payload, map, key); + if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup hit failed"); + return &kh_value(map, k); + } + + void lookup_miss(const EntityId& key) { + khiter_t k = kh_get(entity_payload, map, key); + if (k != kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup miss failed"); + benchmark::DoNotOptimize(k); + } + + void erase(const EntityId& key) { + khiter_t k = kh_get(entity_payload, map, key); + if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "erase failed"); + kh_del(entity_payload, map, k); + } +}; + +// Adapter for ComponentKey -> ComponentMeta +struct KlibComponentAdapter { + khash_t(component_meta) * map = nullptr; + + KlibComponentAdapter() { map = kh_init(component_meta); } + + ~KlibComponentAdapter() { + if (map != nullptr) kh_destroy(component_meta, map); + } + + KlibComponentAdapter(const KlibComponentAdapter&) = delete; + KlibComponentAdapter& operator=(const KlibComponentAdapter&) = delete; + + void reserve(std::size_t count) { benchmark::DoNotOptimize(count); } + + void insert(const ComponentKey& key, const ComponentMeta& value) { + int ret; + khiter_t k = kh_put(component_meta, map, key, &ret); + if (ret < 0) panic_impl(__FILE__, __LINE__, "insert failed"); + kh_value(map, k) = value; + } + + ComponentMeta* lookup_hit(const ComponentKey& key) { + khiter_t k = kh_get(component_meta, map, key); + if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup hit failed"); + return &kh_value(map, k); + } + + void lookup_miss(const ComponentKey& key) { + khiter_t k = kh_get(component_meta, map, key); + if (k != kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup miss failed"); + benchmark::DoNotOptimize(k); + } + + void erase(const ComponentKey& key) { + khiter_t k = kh_get(component_meta, map, key); + if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "erase failed"); + kh_del(component_meta, map, k); + } +}; + +static void BM_Insert_Scalar(benchmark::State& state) { + bench_insert( + state, scalar_workload(), {"khash", "c", "Scalar", "Insert"}); +} +static void BM_LookupHit_Scalar(benchmark::State& state) { + bench_lookup_hit( + state, scalar_workload(), {"khash", "c", "Scalar", "LookupHit"}); +} +static void BM_LookupMiss_Scalar(benchmark::State& state) { + bench_lookup_miss( + state, scalar_workload(), {"khash", "c", "Scalar", "LookupMiss"}); +} +static void BM_Erase_Scalar(benchmark::State& state) { + bench_erase( + state, scalar_workload(), {"khash", "c", "Scalar", "Erase"}); +} + +static void BM_Insert_HandlePayload(benchmark::State& state) { + bench_insert( + state, entity_workload(), {"khash", "c", "HandlePayload", "Insert"}); +} +static void BM_LookupHit_HandlePayload(benchmark::State& state) { + bench_lookup_hit( + state, entity_workload(), {"khash", "c", "HandlePayload", "LookupHit"}); +} +static void BM_LookupMiss_HandlePayload(benchmark::State& state) { + bench_lookup_miss( + state, entity_workload(), + {"khash", "c", "HandlePayload", "LookupMiss"}); +} +static void BM_Erase_HandlePayload(benchmark::State& state) { + bench_erase( + state, entity_workload(), {"khash", "c", "HandlePayload", "Erase"}); +} + +static void BM_Insert_CompositeKey(benchmark::State& state) { + bench_insert( + state, component_workload(), {"khash", "c", "CompositeKey", "Insert"}); +} +static void BM_LookupHit_CompositeKey(benchmark::State& state) { + bench_lookup_hit( + state, component_workload(), + {"khash", "c", "CompositeKey", "LookupHit"}); +} +static void BM_LookupMiss_CompositeKey(benchmark::State& state) { + bench_lookup_miss( + state, component_workload(), + {"khash", "c", "CompositeKey", "LookupMiss"}); +} +static void BM_Erase_CompositeKey(benchmark::State& state) { + bench_erase( + state, component_workload(), {"khash", "c", "CompositeKey", "Erase"}); +} + +} // namespace + +BENCHMARK(BM_Insert_Scalar); +BENCHMARK(BM_LookupHit_Scalar); +BENCHMARK(BM_LookupMiss_Scalar); +BENCHMARK(BM_Erase_Scalar); + +BENCHMARK(BM_Insert_HandlePayload); +BENCHMARK(BM_LookupHit_HandlePayload); +BENCHMARK(BM_LookupMiss_HandlePayload); +BENCHMARK(BM_Erase_HandlePayload); + +BENCHMARK(BM_Insert_CompositeKey); +BENCHMARK(BM_LookupHit_CompositeKey); +BENCHMARK(BM_LookupMiss_CompositeKey); +BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/klib_bench.cpp b/benches/klib_bench.cpp deleted file mode 100644 index 97db497..0000000 --- a/benches/klib_bench.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include - -#include "bench_common.hpp" - -extern "C" { -#include "klib/khash.h" -} - -namespace { - -using namespace cmbench; - -// Define khash instances for each key-value type -static inline std::uint64_t kh_hash_u64(std::uint64_t key) { - return hash_xxh_avalanche(key); -} - -static inline int kh_equal_u64(std::uint64_t a, std::uint64_t b) { - return a == b; -} - -KHASH_INIT(u64_scalar, std::uint64_t, ScalarValue, 1, kh_hash_u64, kh_equal_u64) - -static inline std::uint64_t kh_hash_entity(EntityId key) { - return hash_xxh_avalanche(key); -} - -static inline int kh_equal_entity(EntityId a, EntityId b) { - return byte_equal(a, b); -} - -KHASH_INIT(entity_payload, EntityId, ComponentPayload, 1, kh_hash_entity, - kh_equal_entity) - -static inline std::uint64_t kh_hash_component(ComponentKey key) { - return hash_xxh_avalanche(key); -} - -static inline int kh_equal_component(ComponentKey a, ComponentKey b) { - return byte_equal(a, b); -} - -KHASH_INIT(component_meta, ComponentKey, ComponentMeta, 1, kh_hash_component, - kh_equal_component) - -// Adapter for u64 -> ScalarValue -struct KlibScalarAdapter { - khash_t(u64_scalar) * map = nullptr; - - KlibScalarAdapter() { map = kh_init(u64_scalar); } - - ~KlibScalarAdapter() { - if (map != nullptr) kh_destroy(u64_scalar, map); - } - - KlibScalarAdapter(const KlibScalarAdapter&) = delete; - KlibScalarAdapter& operator=(const KlibScalarAdapter&) = delete; - - void reserve(std::size_t count) { benchmark::DoNotOptimize(count); } - - void insert(const std::uint64_t& key, const ScalarValue& value) { - int ret; - khiter_t k = kh_put(u64_scalar, map, key, &ret); - if (ret < 0) panic_impl(__FILE__, __LINE__, "insert failed"); - kh_value(map, k) = value; - } - - ScalarValue* lookup_hit(const std::uint64_t& key) { - khiter_t k = kh_get(u64_scalar, map, key); - if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup hit failed"); - return &kh_value(map, k); - } - - void lookup_miss(const std::uint64_t& key) { - khiter_t k = kh_get(u64_scalar, map, key); - if (k != kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup miss failed"); - benchmark::DoNotOptimize(k); - } - - void erase(const std::uint64_t& key) { - khiter_t k = kh_get(u64_scalar, map, key); - if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "erase failed"); - kh_del(u64_scalar, map, k); - } -}; - -// Adapter for EntityId -> ComponentPayload -struct KlibEntityAdapter { - khash_t(entity_payload) * map = nullptr; - - KlibEntityAdapter() { map = kh_init(entity_payload); } - - ~KlibEntityAdapter() { - if (map != nullptr) kh_destroy(entity_payload, map); - } - - KlibEntityAdapter(const KlibEntityAdapter&) = delete; - KlibEntityAdapter& operator=(const KlibEntityAdapter&) = delete; - - void reserve(std::size_t count) { benchmark::DoNotOptimize(count); } - - void insert(const EntityId& key, const ComponentPayload& value) { - int ret; - khiter_t k = kh_put(entity_payload, map, key, &ret); - if (ret < 0) panic_impl(__FILE__, __LINE__, "insert failed"); - kh_value(map, k) = value; - } - - ComponentPayload* lookup_hit(const EntityId& key) { - khiter_t k = kh_get(entity_payload, map, key); - if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup hit failed"); - return &kh_value(map, k); - } - - void lookup_miss(const EntityId& key) { - khiter_t k = kh_get(entity_payload, map, key); - if (k != kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup miss failed"); - benchmark::DoNotOptimize(k); - } - - void erase(const EntityId& key) { - khiter_t k = kh_get(entity_payload, map, key); - if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "erase failed"); - kh_del(entity_payload, map, k); - } -}; - -// Adapter for ComponentKey -> ComponentMeta -struct KlibComponentAdapter { - khash_t(component_meta) * map = nullptr; - - KlibComponentAdapter() { map = kh_init(component_meta); } - - ~KlibComponentAdapter() { - if (map != nullptr) kh_destroy(component_meta, map); - } - - KlibComponentAdapter(const KlibComponentAdapter&) = delete; - KlibComponentAdapter& operator=(const KlibComponentAdapter&) = delete; - - void reserve(std::size_t count) { benchmark::DoNotOptimize(count); } - - void insert(const ComponentKey& key, const ComponentMeta& value) { - int ret; - khiter_t k = kh_put(component_meta, map, key, &ret); - if (ret < 0) panic_impl(__FILE__, __LINE__, "insert failed"); - kh_value(map, k) = value; - } - - ComponentMeta* lookup_hit(const ComponentKey& key) { - khiter_t k = kh_get(component_meta, map, key); - if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup hit failed"); - return &kh_value(map, k); - } - - void lookup_miss(const ComponentKey& key) { - khiter_t k = kh_get(component_meta, map, key); - if (k != kh_end(map)) panic_impl(__FILE__, __LINE__, "lookup miss failed"); - benchmark::DoNotOptimize(k); - } - - void erase(const ComponentKey& key) { - khiter_t k = kh_get(component_meta, map, key); - if (k == kh_end(map)) panic_impl(__FILE__, __LINE__, "erase failed"); - kh_del(component_meta, map, k); - } -}; - -static void BM_Insert_Scalar(benchmark::State& state) { - bench_insert( - state, scalar_workload(), {"khash", "c", "Scalar", "Insert"}); -} -static void BM_LookupHit_Scalar(benchmark::State& state) { - bench_lookup_hit( - state, scalar_workload(), {"khash", "c", "Scalar", "LookupHit"}); -} -static void BM_LookupMiss_Scalar(benchmark::State& state) { - bench_lookup_miss( - state, scalar_workload(), {"khash", "c", "Scalar", "LookupMiss"}); -} -static void BM_Erase_Scalar(benchmark::State& state) { - bench_erase( - state, scalar_workload(), {"khash", "c", "Scalar", "Erase"}); -} - -static void BM_Insert_HandlePayload(benchmark::State& state) { - bench_insert( - state, entity_workload(), {"khash", "c", "HandlePayload", "Insert"}); -} -static void BM_LookupHit_HandlePayload(benchmark::State& state) { - bench_lookup_hit( - state, entity_workload(), {"khash", "c", "HandlePayload", "LookupHit"}); -} -static void BM_LookupMiss_HandlePayload(benchmark::State& state) { - bench_lookup_miss( - state, entity_workload(), - {"khash", "c", "HandlePayload", "LookupMiss"}); -} -static void BM_Erase_HandlePayload(benchmark::State& state) { - bench_erase( - state, entity_workload(), {"khash", "c", "HandlePayload", "Erase"}); -} - -static void BM_Insert_CompositeKey(benchmark::State& state) { - bench_insert( - state, component_workload(), {"khash", "c", "CompositeKey", "Insert"}); -} -static void BM_LookupHit_CompositeKey(benchmark::State& state) { - bench_lookup_hit( - state, component_workload(), - {"khash", "c", "CompositeKey", "LookupHit"}); -} -static void BM_LookupMiss_CompositeKey(benchmark::State& state) { - bench_lookup_miss( - state, component_workload(), - {"khash", "c", "CompositeKey", "LookupMiss"}); -} -static void BM_Erase_CompositeKey(benchmark::State& state) { - bench_erase( - state, component_workload(), {"khash", "c", "CompositeKey", "Erase"}); -} - -} // namespace - -BENCHMARK(BM_Insert_Scalar); -BENCHMARK(BM_LookupHit_Scalar); -BENCHMARK(BM_LookupMiss_Scalar); -BENCHMARK(BM_Erase_Scalar); - -BENCHMARK(BM_Insert_HandlePayload); -BENCHMARK(BM_LookupHit_HandlePayload); -BENCHMARK(BM_LookupMiss_HandlePayload); -BENCHMARK(BM_Erase_HandlePayload); - -BENCHMARK(BM_Insert_CompositeKey); -BENCHMARK(BM_LookupHit_CompositeKey); -BENCHMARK(BM_LookupMiss_CompositeKey); -BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/tidwall_bench.cc b/benches/tidwall_bench.cc new file mode 100644 index 0000000..3d8fba8 --- /dev/null +++ b/benches/tidwall_bench.cc @@ -0,0 +1,85 @@ +#include + +#include "bench_common.h" + +namespace { + +using namespace cmbench; + +static void BM_Insert_Scalar(benchmark::State& state) { + bench_insert>( + state, scalar_workload(), {"tidwall_hashmap", "c", "Scalar", "Insert"}); +} +static void BM_LookupHit_Scalar(benchmark::State& state) { + bench_lookup_hit>( + state, scalar_workload(), + {"tidwall_hashmap", "c", "Scalar", "LookupHit"}); +} +static void BM_LookupMiss_Scalar(benchmark::State& state) { + bench_lookup_miss>( + state, scalar_workload(), + {"tidwall_hashmap", "c", "Scalar", "LookupMiss"}); +} +static void BM_Erase_Scalar(benchmark::State& state) { + bench_erase>( + state, scalar_workload(), {"tidwall_hashmap", "c", "Scalar", "Erase"}); +} + +static void BM_Insert_HandlePayload(benchmark::State& state) { + bench_insert>( + state, entity_workload(), + {"tidwall_hashmap", "c", "HandlePayload", "Insert"}); +} +static void BM_LookupHit_HandlePayload(benchmark::State& state) { + bench_lookup_hit>( + state, entity_workload(), + {"tidwall_hashmap", "c", "HandlePayload", "LookupHit"}); +} +static void BM_LookupMiss_HandlePayload(benchmark::State& state) { + bench_lookup_miss>( + state, entity_workload(), + {"tidwall_hashmap", "c", "HandlePayload", "LookupMiss"}); +} +static void BM_Erase_HandlePayload(benchmark::State& state) { + bench_erase>( + state, entity_workload(), + {"tidwall_hashmap", "c", "HandlePayload", "Erase"}); +} + +static void BM_Insert_CompositeKey(benchmark::State& state) { + bench_insert>( + state, component_workload(), + {"tidwall_hashmap", "c", "CompositeKey", "Insert"}); +} +static void BM_LookupHit_CompositeKey(benchmark::State& state) { + bench_lookup_hit>( + state, component_workload(), + {"tidwall_hashmap", "c", "CompositeKey", "LookupHit"}); +} +static void BM_LookupMiss_CompositeKey(benchmark::State& state) { + bench_lookup_miss>( + state, component_workload(), + {"tidwall_hashmap", "c", "CompositeKey", "LookupMiss"}); +} +static void BM_Erase_CompositeKey(benchmark::State& state) { + bench_erase>( + state, component_workload(), + {"tidwall_hashmap", "c", "CompositeKey", "Erase"}); +} + +} // namespace + +BENCHMARK(BM_Insert_Scalar); +BENCHMARK(BM_LookupHit_Scalar); +BENCHMARK(BM_LookupMiss_Scalar); +BENCHMARK(BM_Erase_Scalar); + +BENCHMARK(BM_Insert_HandlePayload); +BENCHMARK(BM_LookupHit_HandlePayload); +BENCHMARK(BM_LookupMiss_HandlePayload); +BENCHMARK(BM_Erase_HandlePayload); + +BENCHMARK(BM_Insert_CompositeKey); +BENCHMARK(BM_LookupHit_CompositeKey); +BENCHMARK(BM_LookupMiss_CompositeKey); +BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/tidwall_bench.cpp b/benches/tidwall_bench.cpp deleted file mode 100644 index 7780876..0000000 --- a/benches/tidwall_bench.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include - -#include "bench_common.hpp" - -namespace { - -using namespace cmbench; - -static void BM_Insert_Scalar(benchmark::State& state) { - bench_insert>( - state, scalar_workload(), {"tidwall_hashmap", "c", "Scalar", "Insert"}); -} -static void BM_LookupHit_Scalar(benchmark::State& state) { - bench_lookup_hit>( - state, scalar_workload(), - {"tidwall_hashmap", "c", "Scalar", "LookupHit"}); -} -static void BM_LookupMiss_Scalar(benchmark::State& state) { - bench_lookup_miss>( - state, scalar_workload(), - {"tidwall_hashmap", "c", "Scalar", "LookupMiss"}); -} -static void BM_Erase_Scalar(benchmark::State& state) { - bench_erase>( - state, scalar_workload(), {"tidwall_hashmap", "c", "Scalar", "Erase"}); -} - -static void BM_Insert_HandlePayload(benchmark::State& state) { - bench_insert>( - state, entity_workload(), - {"tidwall_hashmap", "c", "HandlePayload", "Insert"}); -} -static void BM_LookupHit_HandlePayload(benchmark::State& state) { - bench_lookup_hit>( - state, entity_workload(), - {"tidwall_hashmap", "c", "HandlePayload", "LookupHit"}); -} -static void BM_LookupMiss_HandlePayload(benchmark::State& state) { - bench_lookup_miss>( - state, entity_workload(), - {"tidwall_hashmap", "c", "HandlePayload", "LookupMiss"}); -} -static void BM_Erase_HandlePayload(benchmark::State& state) { - bench_erase>( - state, entity_workload(), - {"tidwall_hashmap", "c", "HandlePayload", "Erase"}); -} - -static void BM_Insert_CompositeKey(benchmark::State& state) { - bench_insert>( - state, component_workload(), - {"tidwall_hashmap", "c", "CompositeKey", "Insert"}); -} -static void BM_LookupHit_CompositeKey(benchmark::State& state) { - bench_lookup_hit>( - state, component_workload(), - {"tidwall_hashmap", "c", "CompositeKey", "LookupHit"}); -} -static void BM_LookupMiss_CompositeKey(benchmark::State& state) { - bench_lookup_miss>( - state, component_workload(), - {"tidwall_hashmap", "c", "CompositeKey", "LookupMiss"}); -} -static void BM_Erase_CompositeKey(benchmark::State& state) { - bench_erase>( - state, component_workload(), - {"tidwall_hashmap", "c", "CompositeKey", "Erase"}); -} - -} // namespace - -BENCHMARK(BM_Insert_Scalar); -BENCHMARK(BM_LookupHit_Scalar); -BENCHMARK(BM_LookupMiss_Scalar); -BENCHMARK(BM_Erase_Scalar); - -BENCHMARK(BM_Insert_HandlePayload); -BENCHMARK(BM_LookupHit_HandlePayload); -BENCHMARK(BM_LookupMiss_HandlePayload); -BENCHMARK(BM_Erase_HandlePayload); - -BENCHMARK(BM_Insert_CompositeKey); -BENCHMARK(BM_LookupHit_CompositeKey); -BENCHMARK(BM_LookupMiss_CompositeKey); -BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/unordered_map_bench.cc b/benches/unordered_map_bench.cc new file mode 100644 index 0000000..edbcf65 --- /dev/null +++ b/benches/unordered_map_bench.cc @@ -0,0 +1,87 @@ +#include + +#include "bench_common.h" + +namespace { + +using namespace cmbench; + +static void BM_Insert_Scalar(benchmark::State& state) { + bench_insert>( + state, scalar_workload(), + {"std::unordered_map", "c++", "Scalar", "Insert"}); +} +static void BM_LookupHit_Scalar(benchmark::State& state) { + bench_lookup_hit>( + state, scalar_workload(), + {"std::unordered_map", "c++", "Scalar", "LookupHit"}); +} +static void BM_LookupMiss_Scalar(benchmark::State& state) { + bench_lookup_miss>( + state, scalar_workload(), + {"std::unordered_map", "c++", "Scalar", "LookupMiss"}); +} +static void BM_Erase_Scalar(benchmark::State& state) { + bench_erase>( + state, scalar_workload(), + {"std::unordered_map", "c++", "Scalar", "Erase"}); +} + +static void BM_Insert_HandlePayload(benchmark::State& state) { + bench_insert>( + state, entity_workload(), + {"std::unordered_map", "c++", "HandlePayload", "Insert"}); +} +static void BM_LookupHit_HandlePayload(benchmark::State& state) { + bench_lookup_hit>( + state, entity_workload(), + {"std::unordered_map", "c++", "HandlePayload", "LookupHit"}); +} +static void BM_LookupMiss_HandlePayload(benchmark::State& state) { + bench_lookup_miss>( + state, entity_workload(), + {"std::unordered_map", "c++", "HandlePayload", "LookupMiss"}); +} +static void BM_Erase_HandlePayload(benchmark::State& state) { + bench_erase>( + state, entity_workload(), + {"std::unordered_map", "c++", "HandlePayload", "Erase"}); +} + +static void BM_Insert_CompositeKey(benchmark::State& state) { + bench_insert>( + state, component_workload(), + {"std::unordered_map", "c++", "CompositeKey", "Insert"}); +} +static void BM_LookupHit_CompositeKey(benchmark::State& state) { + bench_lookup_hit>( + state, component_workload(), + {"std::unordered_map", "c++", "CompositeKey", "LookupHit"}); +} +static void BM_LookupMiss_CompositeKey(benchmark::State& state) { + bench_lookup_miss>( + state, component_workload(), + {"std::unordered_map", "c++", "CompositeKey", "LookupMiss"}); +} +static void BM_Erase_CompositeKey(benchmark::State& state) { + bench_erase>( + state, component_workload(), + {"std::unordered_map", "c++", "CompositeKey", "Erase"}); +} + +} // namespace + +BENCHMARK(BM_Insert_Scalar); +BENCHMARK(BM_LookupHit_Scalar); +BENCHMARK(BM_LookupMiss_Scalar); +BENCHMARK(BM_Erase_Scalar); + +BENCHMARK(BM_Insert_HandlePayload); +BENCHMARK(BM_LookupHit_HandlePayload); +BENCHMARK(BM_LookupMiss_HandlePayload); +BENCHMARK(BM_Erase_HandlePayload); + +BENCHMARK(BM_Insert_CompositeKey); +BENCHMARK(BM_LookupHit_CompositeKey); +BENCHMARK(BM_LookupMiss_CompositeKey); +BENCHMARK(BM_Erase_CompositeKey); diff --git a/benches/unordered_map_bench.cpp b/benches/unordered_map_bench.cpp deleted file mode 100644 index a064ebc..0000000 --- a/benches/unordered_map_bench.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include - -#include "bench_common.hpp" - -namespace { - -using namespace cmbench; - -static void BM_Insert_Scalar(benchmark::State& state) { - bench_insert>( - state, scalar_workload(), - {"std::unordered_map", "c++", "Scalar", "Insert"}); -} -static void BM_LookupHit_Scalar(benchmark::State& state) { - bench_lookup_hit>( - state, scalar_workload(), - {"std::unordered_map", "c++", "Scalar", "LookupHit"}); -} -static void BM_LookupMiss_Scalar(benchmark::State& state) { - bench_lookup_miss>( - state, scalar_workload(), - {"std::unordered_map", "c++", "Scalar", "LookupMiss"}); -} -static void BM_Erase_Scalar(benchmark::State& state) { - bench_erase>( - state, scalar_workload(), - {"std::unordered_map", "c++", "Scalar", "Erase"}); -} - -static void BM_Insert_HandlePayload(benchmark::State& state) { - bench_insert>( - state, entity_workload(), - {"std::unordered_map", "c++", "HandlePayload", "Insert"}); -} -static void BM_LookupHit_HandlePayload(benchmark::State& state) { - bench_lookup_hit>( - state, entity_workload(), - {"std::unordered_map", "c++", "HandlePayload", "LookupHit"}); -} -static void BM_LookupMiss_HandlePayload(benchmark::State& state) { - bench_lookup_miss>( - state, entity_workload(), - {"std::unordered_map", "c++", "HandlePayload", "LookupMiss"}); -} -static void BM_Erase_HandlePayload(benchmark::State& state) { - bench_erase>( - state, entity_workload(), - {"std::unordered_map", "c++", "HandlePayload", "Erase"}); -} - -static void BM_Insert_CompositeKey(benchmark::State& state) { - bench_insert>( - state, component_workload(), - {"std::unordered_map", "c++", "CompositeKey", "Insert"}); -} -static void BM_LookupHit_CompositeKey(benchmark::State& state) { - bench_lookup_hit>( - state, component_workload(), - {"std::unordered_map", "c++", "CompositeKey", "LookupHit"}); -} -static void BM_LookupMiss_CompositeKey(benchmark::State& state) { - bench_lookup_miss>( - state, component_workload(), - {"std::unordered_map", "c++", "CompositeKey", "LookupMiss"}); -} -static void BM_Erase_CompositeKey(benchmark::State& state) { - bench_erase>( - state, component_workload(), - {"std::unordered_map", "c++", "CompositeKey", "Erase"}); -} - -} // namespace - -BENCHMARK(BM_Insert_Scalar); -BENCHMARK(BM_LookupHit_Scalar); -BENCHMARK(BM_LookupMiss_Scalar); -BENCHMARK(BM_Erase_Scalar); - -BENCHMARK(BM_Insert_HandlePayload); -BENCHMARK(BM_LookupHit_HandlePayload); -BENCHMARK(BM_LookupMiss_HandlePayload); -BENCHMARK(BM_Erase_HandlePayload); - -BENCHMARK(BM_Insert_CompositeKey); -BENCHMARK(BM_LookupHit_CompositeKey); -BENCHMARK(BM_LookupMiss_CompositeKey); -BENCHMARK(BM_Erase_CompositeKey); -- cgit v1.2.3