1+ // #region [Headers]
2+ #include < array>
3+ #include < benchmark/benchmark.h>
4+ #include < map>
5+ #include < type_traits>
6+ #include < unordered_map>
7+ #include < vector>
8+ // #endregion
9+ // #region [Configs]
10+ #define COUNT 500
11+ #define SIZE 1000
12+
13+ // local traits
14+ struct UnsafeMode {};
15+ struct SafeMode {};
16+ struct InOrder {};
17+ struct RandomOrder {};
18+ // #endregion
19+ // #region [Dummy structures]
20+ struct DummyValue {
21+ template <typename T> void operator =(const T &) {}
22+ operator int () { return 1 ; }
23+ };
24+ struct DummyContainer {
25+ DummyValue operator [](std::size_t ) { return {}; }
26+ DummyValue at (std::size_t ) { return {}; }
27+ };
28+ // #endregion
29+
30+ template <typename Mode, typename Order, typename Container, auto ... args>
31+ void bench (benchmark::State &state) {
32+ benchmark::ClobberMemory ();
33+ Container c (args...);
34+ benchmark::DoNotOptimize (c);
35+ for (std::size_t i = 0 ; i < SIZE; ++i) // same way to fill all container
36+ c[i] = 1 ; // not the most efficient for all
37+ auto indexer = []() {
38+ if constexpr (std::is_same_v<Order, RandomOrder>) {
39+ return [](const int i) {
40+ const unsigned i2 = i ^ 0x7777'7777 ;
41+ return (((i2 >> 16 ) + (i2 << 16 )) % SIZE);
42+ };
43+ } else {
44+ static_assert (std::is_same_v<Order, InOrder>);
45+ return [](const int i) { return i; };
46+ }
47+ }();
48+
49+ for (auto _ : state) {
50+ int val = 0 ;
51+ for (int i = 0 ; i < COUNT; ++i) {
52+ if constexpr (std::is_same_v<Mode, UnsafeMode>) {
53+ val += c[indexer (i)];
54+ } else {
55+ static_assert (std::is_same_v<Mode, SafeMode>);
56+ val += c.at (indexer (i));
57+ }
58+ }
59+ benchmark::DoNotOptimize (val);
60+ benchmark::ClobberMemory ();
61+ }
62+ }
63+
64+ #define ORDER RandomOrder // TODO Change me: InOrder or RandomOrder
65+ #define COMMA , // google benchmark macro does not support true comma
66+ BENCHMARK_TEMPLATE (bench, SafeMode, ORDER, DummyContainer)
67+ ->Name(" Do Nothing Reference" );
68+ BENCHMARK_TEMPLATE (bench, UnsafeMode, ORDER, std::array<int COMMA SIZE>)
69+ ->Name(" array::operator[]" );
70+ BENCHMARK_TEMPLATE (bench, SafeMode, ORDER, std::array<int COMMA SIZE>)
71+ ->Name(" array::at" );
72+ BENCHMARK_TEMPLATE (bench, UnsafeMode, ORDER, std::vector<int >, SIZE)
73+ ->Name(" vector::operator[]" );
74+ BENCHMARK_TEMPLATE (bench, SafeMode, ORDER, std::vector<int >, SIZE)
75+ ->Name(" vector::at" );
76+ BENCHMARK_TEMPLATE (bench, UnsafeMode, ORDER, std::map<int COMMA int >)
77+ ->Name(" map::operator[]" );
78+ BENCHMARK_TEMPLATE (bench, SafeMode, ORDER, std::map<int COMMA int >)
79+ ->Name(" map::at" );
80+ BENCHMARK_TEMPLATE (bench, UnsafeMode, ORDER, std::unordered_map<int COMMA int >)
81+ ->Name(" unordered_map::operator[]" );
82+ BENCHMARK_TEMPLATE (bench, SafeMode, ORDER, std::unordered_map<int COMMA int >)
83+ ->Name(" unordered_map::at" );
84+
85+ BENCHMARK_MAIN ();
0 commit comments