-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
Fixed*Map
data structures
This adds a new set of tests tagged "benchmark" in bazel, which are filtered out of the default `test_suite` target. This means that they will only be built/run manually.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#include "fixed_containers/fixed_map.hpp" | ||
#include "fixed_containers/fixed_unordered_map.hpp" | ||
|
||
#include <benchmark/benchmark.h> | ||
|
||
#include <array> | ||
#include <cstddef> | ||
#include <cstdint> | ||
#include <map> | ||
#include <unordered_map> | ||
|
||
namespace fixed_containers | ||
{ | ||
|
||
namespace | ||
{ | ||
template <typename MapType> | ||
[[maybe_unused]] void benchmark_map_copy(benchmark::State& state) | ||
{ | ||
const int64_t nelem = state.range(0); | ||
MapType instance = {}; | ||
|
||
using KeyType = typename MapType::key_type; | ||
for (int64_t i = 0; i < nelem; i++) | ||
{ | ||
instance.try_emplace(static_cast<KeyType>(i)); | ||
} | ||
|
||
for (const auto& iter : state) | ||
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 29 in test/benchmarks/map_clear.cpp GitHub Actions / build
|
||
{ | ||
MapType instance2{instance}; | ||
benchmark::DoNotOptimize(instance2); | ||
} | ||
} | ||
|
||
template <typename MapType> | ||
[[maybe_unused]] void benchmark_map_copy_then_clear(benchmark::State& state) | ||
{ | ||
using KeyType = typename MapType::key_type; | ||
MapType instance{}; | ||
const int64_t nelem = state.range(0); | ||
for (int64_t i = 0; i < nelem; i++) | ||
{ | ||
instance.try_emplace(static_cast<KeyType>(i)); | ||
} | ||
|
||
for (const auto& iter : state) | ||
Check failure on line 47 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 47 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 47 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 47 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 47 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 47 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 47 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 47 in test/benchmarks/map_clear.cpp GitHub Actions / build
|
||
{ | ||
MapType instance2{instance}; | ||
instance2.clear(); | ||
benchmark::DoNotOptimize(instance2); | ||
} | ||
} | ||
|
||
template <typename MapType> | ||
[[maybe_unused]] void benchmark_map_copy_then_reconstruct(benchmark::State& state) | ||
{ | ||
using KeyType = typename MapType::key_type; | ||
MapType instance{}; | ||
const int64_t nelem = state.range(0); | ||
for (int64_t i = 0; i < nelem; i++) | ||
{ | ||
instance.try_emplace(static_cast<KeyType>(i)); | ||
} | ||
|
||
for (const auto& iter : state) | ||
Check failure on line 66 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 66 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 66 in test/benchmarks/map_clear.cpp GitHub Actions / Analyze (cpp, gcc-11, Ninja, Debug, OFF)
Check failure on line 66 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 66 in test/benchmarks/map_clear.cpp GitHub Actions / build
Check failure on line 66 in test/benchmarks/map_clear.cpp GitHub Actions / build
|
||
{ | ||
MapType instance2{instance}; | ||
instance2 = {}; | ||
benchmark::DoNotOptimize(instance2); | ||
} | ||
} | ||
|
||
template <typename ArrType> | ||
[[maybe_unused]] void benchmark_array_clear(benchmark::State& state) | ||
{ | ||
ArrType instance{}; | ||
|
||
for (const auto& iter : state) | ||
{ | ||
instance.fill(0); | ||
benchmark::DoNotOptimize(instance); | ||
} | ||
} | ||
} // namespace | ||
|
||
constexpr std::size_t MAX_SIZE = 8 << 13; | ||
|
||
BENCHMARK(benchmark_map_copy<std::map<int, int>>)->Range(16, MAX_SIZE); | ||
BENCHMARK(benchmark_map_copy_then_clear<std::map<int, int>>)->Range(16, MAX_SIZE); | ||
BENCHMARK(benchmark_map_copy_then_reconstruct<std::map<int, int>>)->Range(16, MAX_SIZE); | ||
|
||
BENCHMARK(benchmark_map_copy<std::unordered_map<int, int>>)->Range(16, MAX_SIZE); | ||
BENCHMARK(benchmark_map_copy_then_clear<std::unordered_map<int, int>>)->Range(16, MAX_SIZE); | ||
BENCHMARK(benchmark_map_copy_then_reconstruct<std::unordered_map<int, int>>)->Range(16, MAX_SIZE); | ||
|
||
BENCHMARK(benchmark_map_copy<FixedMap<int, int, MAX_SIZE>>)->Range(16, MAX_SIZE); | ||
BENCHMARK(benchmark_map_copy_then_clear<FixedMap<int, int, MAX_SIZE>>)->Range(16, MAX_SIZE); | ||
BENCHMARK(benchmark_map_copy_then_reconstruct<FixedMap<int, int, MAX_SIZE>>)->Range(16, MAX_SIZE); | ||
|
||
BENCHMARK(benchmark_map_copy<FixedUnorderedMap<int, int, MAX_SIZE>>)->Range(16, MAX_SIZE); | ||
BENCHMARK(benchmark_map_copy_then_clear<FixedUnorderedMap<int, int, MAX_SIZE>>) | ||
->Range(16, MAX_SIZE); | ||
BENCHMARK(benchmark_map_copy_then_reconstruct<FixedUnorderedMap<int, int, MAX_SIZE>>) | ||
->Range(16, MAX_SIZE); | ||
|
||
// more-or-less the theoretical best performance we could possibly get for a full FixedUnorderedMap | ||
// (just 0 out every bucket) | ||
BENCHMARK(benchmark_array_clear<std::array<long, (MAX_SIZE * 130ULL) / 100>>); | ||
|
||
} // namespace fixed_containers | ||
|
||
BENCHMARK_MAIN(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
#include "map_utils.hpp" | ||
|
||
#include "../mock_testing_types.hpp" | ||
#include "fixed_containers/fixed_unordered_map.hpp" | ||
|
||
#include <benchmark/benchmark.h> | ||
|
||
#include <cstdint> | ||
|
||
namespace fixed_containers | ||
{ | ||
|
||
namespace | ||
{ | ||
template <typename MapType> | ||
[[maybe_unused]] void benchmark_map_copy_fresh(benchmark::State& state) | ||
{ | ||
const int64_t nelem = state.range(0); | ||
MapType instance = {}; | ||
|
||
using KeyType = typename MapType::key_type; | ||
for (int64_t i = 0; i < nelem; i++) | ||
{ | ||
instance.try_emplace(static_cast<KeyType>(i)); | ||
} | ||
|
||
for (const auto& iter : state) | ||
{ | ||
MapType instance2{instance}; | ||
benchmark::DoNotOptimize(instance2); | ||
} | ||
} | ||
|
||
template <typename MapType> | ||
[[maybe_unused]] void benchmark_map_iterate_copy_fresh(benchmark::State& state) | ||
{ | ||
const int64_t nelem = state.range(0); | ||
MapType instance = {}; | ||
|
||
using KeyType = typename MapType::key_type; | ||
for (int64_t i = 0; i < nelem; i++) | ||
{ | ||
instance.try_emplace(static_cast<KeyType>(i)); | ||
} | ||
|
||
for (const auto& iter : state) | ||
{ | ||
MapType instance2{}; | ||
for (const auto& elem : instance) | ||
{ | ||
instance2.try_emplace(elem.first, elem.second); | ||
} | ||
benchmark::DoNotOptimize(instance2); | ||
} | ||
} | ||
|
||
template <typename MapType> | ||
[[maybe_unused]] void benchmark_map_copy_shuffled(benchmark::State& state) | ||
{ | ||
const int64_t nelem = state.range(0); | ||
auto instance = map_benchmarks::make_shuffled_map<MapType>(); | ||
|
||
using KeyType = typename MapType::key_type; | ||
for (int64_t i = 0; i < nelem; i++) | ||
{ | ||
instance.try_emplace(static_cast<KeyType>(i)); | ||
} | ||
|
||
for (const auto& iter : state) | ||
{ | ||
MapType instance2{instance}; | ||
benchmark::DoNotOptimize(instance2); | ||
} | ||
} | ||
|
||
template <typename MapType> | ||
[[maybe_unused]] void benchmark_map_iterate_copy_shuffled(benchmark::State& state) | ||
{ | ||
const int64_t nelem = state.range(0); | ||
auto instance = map_benchmarks::make_shuffled_map<MapType>(); | ||
|
||
using KeyType = typename MapType::key_type; | ||
for (int64_t i = 0; i < nelem; i++) | ||
{ | ||
instance.try_emplace(static_cast<KeyType>(i)); | ||
} | ||
|
||
for (const auto& iter : state) | ||
{ | ||
MapType instance2{}; | ||
for (const auto& elem : instance) | ||
{ | ||
instance2.try_emplace(elem.first, elem.second); | ||
} | ||
benchmark::DoNotOptimize(instance2); | ||
} | ||
} | ||
} // namespace | ||
|
||
BENCHMARK( | ||
benchmark_map_copy_fresh<FixedUnorderedMap<int, MockNonTrivialCopyConstructible, 8 << 14>>) | ||
->DenseRange(1024, 8 << 14, 1024); | ||
BENCHMARK(benchmark_map_iterate_copy_fresh< | ||
FixedUnorderedMap<int, MockNonTrivialCopyConstructible, 8 << 14>>) | ||
->DenseRange(1024, 8 << 14, 1024); | ||
|
||
BENCHMARK( | ||
benchmark_map_copy_shuffled<FixedUnorderedMap<int, MockNonTrivialCopyConstructible, 8 << 14>>) | ||
->DenseRange(1024, 8 << 14, 1024); | ||
BENCHMARK(benchmark_map_iterate_copy_shuffled< | ||
FixedUnorderedMap<int, MockNonTrivialCopyConstructible, 8 << 14>>) | ||
->DenseRange(1024, 8 << 14, 1024); | ||
|
||
} // namespace fixed_containers | ||
|
||
BENCHMARK_MAIN(); |