#include // for map #include // for name_of_type #include // for Rng #include // for TestCase, skip, ResultBuilder #include // for format, print #include // for fill_n #include // for array #include // for duration, operator-, steady_clock #include // for size_t #include // for unordered_map, operator!= #include // for vector template void bench() { static constexpr size_t num_total = 4; auto required_checksum = std::array{200000, 25198620, 50197240, 75195862, 100194482}; auto total = std::chrono::steady_clock::duration(); for (size_t num_found = 0; num_found < 5; ++num_found) { auto title = fmt::format("random find {}% success {}", num_found * 100 / num_total, name_of_type()); auto rng = ankerl::nanobench::Rng(123); size_t checksum = 0; using ary_t = std::array; auto insert_random = ary_t(); insert_random.fill(true); for (typename ary_t::size_type i = 0; i < num_found; ++i) { insert_random[i] = false; } auto another_unrelated_rng = ankerl::nanobench::Rng(987654321); auto const another_unrelated_rng_initial_state = another_unrelated_rng.state(); auto find_rng = ankerl::nanobench::Rng(another_unrelated_rng_initial_state); { static constexpr size_t num_inserts = 200000; static constexpr size_t num_finds_per_insert = 500; static constexpr size_t num_finds_per_iter = num_finds_per_insert * num_total; Map map; size_t i = 0; size_t find_count = 0; auto before = std::chrono::steady_clock::now(); do { // insert numTotal entries: some random, some sequential. rng.shuffle(insert_random); for (bool const is_random_to_insert : insert_random) { auto val = another_unrelated_rng(); if (is_random_to_insert) { map[static_cast(rng())] = static_cast(1); } else { map[static_cast(val)] = static_cast(1); } ++i; } // the actual benchmark code which should be as fast as possible for (size_t j = 0; j < num_finds_per_iter; ++j) { if (++find_count > i) { find_count = 0; find_rng = ankerl::nanobench::Rng(another_unrelated_rng_initial_state); } auto it = map.find(static_cast(find_rng())); if (it != map.end()) { checksum += it->second; } } } while (i < num_inserts); checksum += map.size(); auto after = std::chrono::steady_clock::now(); total += after - before; fmt::print("{}s {}\n", std::chrono::duration(after - before).count(), title); } REQUIRE(checksum == required_checksum[num_found]); } fmt::print("{}s total\n", std::chrono::duration(total).count()); } // 26.81 TEST_CASE("bench_find_random_uo" * doctest::test_suite("bench") * doctest::skip()) { bench>(); } #if 0 // 10.55 TEST_CASE("bench_find_random_rh" * doctest::test_suite("bench") * doctest::skip()) { bench>(); } #endif // 8.87 TEST_CASE_MAP("bench_find_random_udm" * doctest::test_suite("bench") * doctest::skip(), size_t, size_t) { bench(); }