diff --git a/perfect_hashing/Makefile b/perfect_hashing/Makefile index 89a10bb..0d93b0f 100644 --- a/perfect_hashing/Makefile +++ b/perfect_hashing/Makefile @@ -28,7 +28,7 @@ gperf: %: ${CXX} \ - -I. -I.. -I ~/Projects/boost-1.85 ${CXXFLAGS} ${CONSTEXPR_LIMIT} \ + -I. -I.. -I ~/Projects/boost-1.85 ${CXXFLAGS} -DNTEST ${CONSTEXPR_LIMIT} \ -DSIZE=${SIZE} \ -DPROBABILITY=${PROBABILITY} \ -DSEED=${SEED} \ diff --git a/perfect_hashing/benchmark.hpp b/perfect_hashing/benchmark.hpp index f9a3950..8d63765 100644 --- a/perfect_hashing/benchmark.hpp +++ b/perfect_hashing/benchmark.hpp @@ -7,9 +7,6 @@ // #pragma once -#ifndef NTEST -#define NTEST -#endif #include #include #include @@ -34,7 +31,7 @@ void timeit(const auto& fn) { std::cout << checksum << ":" << std::chrono::duration_cast(stop - start).count() / double(1e9) << std::endl; } -template +template class Benchmark, auto N = 100'000, const auto& input = DATA> [[nodiscard]] auto int_to_int(auto fn) { using key_type = decltype(input[0].first); using mapped_type = decltype(input[0].second); @@ -48,17 +45,18 @@ template lookups(Size * N); for (auto i = 0u; i < lookups.size(); ++i) lookups[i] = data[(i % 100) < (Probability * 100)][i]; + Benchmark benchmark{}; timeit([&]{ u64 checksum{}; for (const auto& lookup: lookups) { - checksum += (fn.template operator()(lookup) != mapped_type{}); + checksum += (benchmark(lookup) != mapped_type{}); } return checksum; }); } -template -[[nodiscard]] auto str_to_int(auto fn) { +template class Benchmark, auto N = 100'000, const auto& input = DATA> +[[nodiscard]] auto str_to_int() { using key_type = decltype(input[0].first); using mapped_type = decltype(input[0].second); std::mt19937_64 gen{Seed}; @@ -71,10 +69,11 @@ template lookups(Size * N); for (auto i = 0u; i < lookups.size(); ++i) lookups[i] = data[(i % 100) < (Probability * 100)][i]; + Benchmark benchmark{}; timeit([&]{ u64 checksum{}; for (const auto& lookup: lookups) { - checksum += fn.template operator()(lookup); + checksum += benchmark(lookup); } return checksum; }); diff --git a/perfect_hashing/boost_unordered_flat_map.cpp b/perfect_hashing/boost_unordered_flat_map.cpp index a6e63a7..a47cd99 100644 --- a/perfect_hashing/boost_unordered_flat_map.cpp +++ b/perfect_hashing/boost_unordered_flat_map.cpp @@ -8,15 +8,16 @@ #include #include -template -auto find(auto value) { - static const auto values = [](std::index_sequence) { - return boost::unordered_flat_map{entries[Ns]...}; - }(std::make_index_sequence{}); - const auto it = values.find(value); - return it != values.end() ? it->second : decltype(it->second){}; -} +template +struct find { + auto operator()(auto value) const { + const auto it = map.find(value); + return it != map.end() ? it->second : decltype(it->second){}; + } + private: + boost::unordered_flat_map map{entries.begin(), entries.end()}; +}; int main() { - BENCHMARK([](auto value) { return find(value); }); + BENCHMARK(); } diff --git a/perfect_hashing/frozen.cpp b/perfect_hashing/frozen.cpp index 43782b8..a26656c 100644 --- a/perfect_hashing/frozen.cpp +++ b/perfect_hashing/frozen.cpp @@ -6,18 +6,26 @@ // http://www.boost.org/LICENSE_1_0.txt) // #include +#include #include #include -template -auto find(auto value) { - static constexpr auto values = [](std::index_sequence) { - return frozen::unordered_map, std::string_view>, frozen::string, std::remove_cvref_t>, std::remove_cvref_t, entries.size()>{entries[Ns]...}; +template +struct find { + auto operator()(auto value) const { + const auto it = map.find(value); + return it != map.end() ? it->second : decltype(it->second){}; + } + + private: + static constexpr auto map = [](std::index_sequence) { + return frozen::unordered_map< + std::conditional_t, frozen::string, T>, TMapped, + entries.size() + >{entries[Ns]...}; }(std::make_index_sequence{}); - const auto it = values.find(value); - return it != values.end() ? it->second : decltype(it->second){}; -} +}; int main() { - BENCHMARK([](auto value) { return find(value); }); + BENCHMARK(); } diff --git a/perfect_hashing/gperf.cpp b/perfect_hashing/gperf.cpp index 22a7143..20e35c3 100644 --- a/perfect_hashing/gperf.cpp +++ b/perfect_hashing/gperf.cpp @@ -8,15 +8,17 @@ #include #include "/dev/shm/gperf.hpp" -template -auto find(auto value) { - if (auto ptr = Perfect_Hash::find(value.data(), value.size())) { - return ptr->value; - } else { - return decltype(ptr->value){}; +template +struct find { + auto operator()(auto value) const -> TMapped { + if (auto ptr = Perfect_Hash::find(value.data(), value.size())) { + return ptr->value; + } else { + return {}; + } } -} +}; int main() { - BENCHMARK([](auto value) { return find(value); }); + BENCHMARK(); } diff --git a/perfect_hashing/if_else.cpp b/perfect_hashing/if_else.cpp index 5aebbc0..f392ab3 100644 --- a/perfect_hashing/if_else.cpp +++ b/perfect_hashing/if_else.cpp @@ -7,17 +7,19 @@ // #include -template -auto find(auto value) -> decltype(entries[0].second) { - if constexpr (I == entries.size()) { - return {}; - } else if (value == entries[I].first) { - return entries[I].second; - } else { - return find(value); +template +struct find { + template auto operator()(auto value) const -> TMapped { + if constexpr (I == entries.size()) { + return {}; + } else if (value == entries[I].first) { + return entries[I].second; + } else { + return operator()(value); + } } -} +}; int main() { - BENCHMARK([](auto value) { return find(value); }); + BENCHMARK(); } diff --git a/perfect_hashing/map.cpp b/perfect_hashing/map.cpp index 3ea4a9e..e0f6c76 100644 --- a/perfect_hashing/map.cpp +++ b/perfect_hashing/map.cpp @@ -8,15 +8,16 @@ #include #include -template -auto find(auto value) { - static const auto values = [](std::index_sequence) { - return std::map{entries[Ns]...}; - }(std::make_index_sequence{}); - const auto it = values.find(value); - return it != values.end() ? it->second : decltype(it->second){}; -} +template +struct find { + auto operator()(auto value) const { + const auto it = map.find(value); + return it != map.end() ? it->second : decltype(it->second){}; + } + private: + std::map map{entries.begin(), entries.end()}; +}; int main() { - BENCHMARK([](auto value) { return find(value); }); + BENCHMARK(); } diff --git a/perfect_hashing/mph.cpp b/perfect_hashing/mph.cpp index 410176e..2e8191d 100644 --- a/perfect_hashing/mph.cpp +++ b/perfect_hashing/mph.cpp @@ -6,16 +6,15 @@ // http://www.boost.org/LICENSE_1_0.txt) // #include -#ifndef NTEST -#define NTEST -#endif #include -template -auto find(auto value) { - return *mph::find(value); -} +template +struct find { + auto operator()(auto value) const { + return *mph::find(value); + } +}; int main() { - BENCHMARK([](auto value) { return find(value); }); + BENCHMARK(); } diff --git a/perfect_hashing/switch_case.cpp b/perfect_hashing/switch_case.cpp index cdfb74a..1ebdac0 100644 --- a/perfect_hashing/switch_case.cpp +++ b/perfect_hashing/switch_case.cpp @@ -7,21 +7,19 @@ // #include -template -constexpr auto find(auto value) { - const auto switch_case = [value](auto self) { - if constexpr (I == entries.size()) { - return decltype(entries[0].second){}; - } else { - switch (value) { - default: return self.template operator()(self); - case entries[I].first: return entries[I].second; +template +struct find { + auto operator()(auto value) const { + const auto switch_case = [value](auto self) { + if constexpr (I == entries.size()) { + return decltype(entries[0].second){}; + } else { + switch (value) { + default: return self.template operator()(self); + case entries[I].first: return entries[I].second; + } } - } - }; - return switch_case(switch_case); -} - -int main() { - BENCHMARK([](auto value) { return find(value); }); -} + }; + return switch_case(switch_case); + } +}; diff --git a/perfect_hashing/unordered_map.cpp b/perfect_hashing/unordered_map.cpp index cbf2a87..b7904f5 100644 --- a/perfect_hashing/unordered_map.cpp +++ b/perfect_hashing/unordered_map.cpp @@ -8,15 +8,16 @@ #include #include -template -auto find(auto value) { - static const auto values = [](std::index_sequence) { - return std::unordered_map{entries[Ns]...}; - }(std::make_index_sequence{}); - const auto it = values.find(value); - return it != values.end() ? it->second : decltype(it->second){}; -} +template +struct find { + auto operator()(auto value) const { + const auto it = map.find(value); + return it != map.end() ? it->second : decltype(it->second){}; + } + private: + std::unordered_map map{entries.begin(), entries.end()}; +}; int main() { - BENCHMARK([](auto value) { return find(value); }); + BENCHMARK(); }