osrm-backend/test/unit/segmented_vector.cpp
Siarhei Fedartsou f1087e81ec Squashed 'third_party/unordered_dense/' content from commit 231e48c94
git-subtree-dir: third_party/unordered_dense
git-subtree-split: 231e48c9426bd21c273669e5fdcd042c146975cf
2024-05-30 19:06:16 +02:00

138 lines
4.1 KiB
C++

#include <ankerl/unordered_dense.h>
#include <app/counter.h>
#include <app/counting_allocator.h>
#include <app/doctest.h>
#include <cstddef>
#include <third-party/nanobench.h>
#include <deque>
TEST_CASE("segmented_vector") {
counter counts;
INFO(counts);
{
auto vec = ankerl::unordered_dense::segmented_vector<counter::obj>();
for (size_t i = 0; i < 1000; ++i) {
vec.emplace_back(i, counts);
REQUIRE(i + 1 == counts.ctor());
}
REQUIRE(0 == counts.move_ctor());
REQUIRE(0 == counts.move_assign());
counts("before dtor");
REQUIRE(counts.data() == counter::data_t{1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
}
counts.check_all_done();
REQUIRE(0 == counts.move_ctor());
counts("done");
REQUIRE(counts.data() == counter::data_t{1000, 0, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0});
}
TEST_CASE("segmented_vector_capacity") {
counter counts;
INFO(counts);
auto vec =
ankerl::unordered_dense::segmented_vector<counter::obj, std::allocator<counter::obj>, sizeof(counter::obj) * 4>();
REQUIRE(0 == vec.capacity());
for (size_t i = 0; i < 50; ++i) {
REQUIRE(i == vec.size());
vec.emplace_back(i, counts);
REQUIRE(i + 1 == vec.size());
REQUIRE(vec.capacity() >= vec.size());
REQUIRE(0 == vec.capacity() % 4);
}
}
TEST_CASE("segmented_vector_idx") {
counter counts;
INFO(counts);
auto vec =
ankerl::unordered_dense::segmented_vector<counter::obj, std::allocator<counter::obj>, sizeof(counter::obj) * 4>();
REQUIRE(0 == vec.capacity());
for (size_t i = 0; i < 50; ++i) {
vec.emplace_back(i, counts);
}
for (size_t i = 0; i < vec.size(); ++i) {
REQUIRE(i == vec[i].get());
}
}
TEST_CASE("segmented_vector_iterate") {
counter counts;
INFO(counts);
auto vec =
ankerl::unordered_dense::segmented_vector<counter::obj, std::allocator<counter::obj>, sizeof(counter::obj) * 4>();
for (size_t i = 0; i < 50; ++i) {
auto it = vec.begin();
auto end = vec.end();
REQUIRE(std::distance(it, end) == static_cast<std::ptrdiff_t>(vec.size()));
size_t j = 0;
while (it != end) {
REQUIRE(it->get() == j);
++it;
++j;
}
vec.emplace_back(i, counts);
}
}
TEST_CASE("segmented_vector_reserve") {
auto counts = counts_for_allocator{};
auto vec = ankerl::unordered_dense::segmented_vector<int, counting_allocator<int>, sizeof(int) * 16>(&counts);
REQUIRE(0 == vec.capacity());
REQUIRE(counts.size() < 2);
vec.reserve(1100);
REQUIRE(counts.size() > 63);
counts.reset();
REQUIRE(counts.size() == 0);
REQUIRE(1104 == vec.capacity());
for (size_t i = 0; i < vec.capacity(); ++i) {
vec.emplace_back(0);
}
REQUIRE(counts.size() == 0);
vec.emplace_back(123);
// 3: 2 for std::vector<T*> reallocates, 1 for the new segment
REQUIRE(counts.size() == 3);
}
using vec_t = ankerl::unordered_dense::segmented_vector<counter::obj>;
static_assert(sizeof(vec_t) == sizeof(std::vector<counter::obj*>) + sizeof(size_t));
TEST_CASE("bench_segmented_vector" * doctest::test_suite("bench") * doctest::skip()) {
static constexpr auto num_elements = size_t{21233};
using namespace std::literals;
ankerl::nanobench::Rng rng(123);
auto sv = ankerl::unordered_dense::segmented_vector<size_t>();
for (size_t i = 0; i < num_elements; ++i) {
sv.emplace_back(i);
}
ankerl::nanobench::Bench().minEpochTime(100ms).batch(sv.size()).run("shuffle stable_vector", [&] {
rng.shuffle(sv);
});
auto c = std::deque<size_t>();
for (size_t i = 0; i < num_elements; ++i) {
c.push_back(i);
}
ankerl::nanobench::Bench().minEpochTime(100ms).batch(sv.size()).run("shuffle std::deque", [&] {
rng.shuffle(c);
});
auto v = std::vector<size_t>();
for (size_t i = 0; i < num_elements; ++i) {
v.push_back(i);
}
ankerl::nanobench::Bench().minEpochTime(100ms).batch(sv.size()).run("shuffle std::vector", [&] {
rng.shuffle(v);
});
}