165 lines
5.1 KiB
C++
165 lines
5.1 KiB
C++
#include "Facade.h"
|
|
#include "Internal.h"
|
|
|
|
#include <nanobench.h>
|
|
|
|
void monotonicallyIncreasing() {
|
|
constexpr int kWindow = 1000;
|
|
ankerl::nanobench::Bench bench;
|
|
Facade facade{kWindow + 1};
|
|
|
|
bench.minEpochIterations(kWindow * 20);
|
|
|
|
bench.warmup(kWindow).run("monotonically increasing", [&] {
|
|
const int64_t remove = __builtin_bswap64(facade.getVersion() - kWindow);
|
|
const int64_t next = __builtin_bswap64(facade.getVersion());
|
|
weaselab::VersionedMap::Mutation mutations[] = {
|
|
{(const uint8_t *)&remove, 8, nullptr, 0,
|
|
weaselab::VersionedMap::Clear},
|
|
{(const uint8_t *)&next, 8, (const uint8_t *)&next, 8,
|
|
weaselab::VersionedMap::Set},
|
|
};
|
|
facade.addMutations(mutations, sizeof(mutations) / sizeof(mutations[0]),
|
|
facade.getVersion() + 1);
|
|
facade.setOldestVersion(facade.getVersion() - kWindow);
|
|
});
|
|
|
|
const auto v = facade.getVersion() - kWindow / 2;
|
|
const auto begin = facade.versioned.begin(v);
|
|
const auto end = facade.versioned.end(v);
|
|
auto iter = begin;
|
|
|
|
bench.run("*iter", [&] { bench.doNotOptimizeAway(*iter); });
|
|
|
|
iter = begin;
|
|
bench.run("++iter", [&] {
|
|
++iter;
|
|
if (iter == end) {
|
|
iter = begin;
|
|
}
|
|
});
|
|
|
|
iter = end;
|
|
bench.run("--iter", [&] {
|
|
--iter;
|
|
if (iter == begin) {
|
|
iter = end;
|
|
}
|
|
});
|
|
|
|
bench.run("begin", [&] { facade.versioned.begin(v); });
|
|
|
|
bench.run("begin (firstGeq)", [&] {
|
|
weaselab::VersionedMap::Key key{nullptr, 0};
|
|
weaselab::VersionedMap::Iterator iter;
|
|
facade.versioned.firstGeq(&key, &v, &iter, 1);
|
|
});
|
|
|
|
bench.run("end", [&] { facade.versioned.end(v); });
|
|
}
|
|
|
|
void bulkFirstGeq() {
|
|
constexpr int kNumKeys = 100000;
|
|
constexpr int kNumQueries = 100;
|
|
ankerl::nanobench::Bench bench;
|
|
bench.batch(kNumQueries);
|
|
bench.minEpochIterations(kNumQueries * 5);
|
|
|
|
// Initialize `versionedMap`
|
|
weaselab::VersionedMap versionedMap{0};
|
|
for (int64_t i = 0; i < kNumKeys; ++i) {
|
|
const auto bigEndian = __builtin_bswap64(i);
|
|
weaselab::VersionedMap::Mutation m;
|
|
m.param1 = (const uint8_t *)&bigEndian;
|
|
m.param1Len = sizeof(bigEndian);
|
|
m.param2 = (const uint8_t *)&bigEndian;
|
|
m.param2Len = sizeof(bigEndian);
|
|
m.type = weaselab::VersionedMap::Set;
|
|
versionedMap.addMutations(&m, 1, i + 1);
|
|
}
|
|
|
|
// Prepare queries
|
|
Arena arena;
|
|
auto *keys = new (arena) weaselab::VersionedMap::Key[kNumQueries];
|
|
auto *versions = new (arena) int64_t[kNumQueries];
|
|
for (int64_t i = 0; i < kNumQueries; ++i) {
|
|
int64_t key = i * kNumKeys / kNumQueries;
|
|
static_assert(kNumKeys >= kNumQueries);
|
|
versions[i] = kNumKeys - i;
|
|
const auto bigEndian = __builtin_bswap64(key);
|
|
uint8_t *k = new (arena) uint8_t[sizeof(bigEndian)];
|
|
memcpy(k, &bigEndian, sizeof(bigEndian));
|
|
keys[i].p = k;
|
|
keys[i].len = sizeof(bigEndian);
|
|
}
|
|
|
|
weaselab::VersionedMap::Iterator iterators[kNumQueries];
|
|
// Bench
|
|
bench.run("bulkFirstGeq", [&] {
|
|
versionedMap.firstGeq(keys, versions, iterators, kNumQueries);
|
|
});
|
|
|
|
bench.run("bulkFirstGeq (latest version)",
|
|
[&] { versionedMap.firstGeq(keys, iterators, kNumQueries); });
|
|
}
|
|
|
|
void facadeVersionedOnlyRead() {
|
|
Facade facade{0};
|
|
constexpr int kNumKeys = 10000;
|
|
ankerl::nanobench::Bench bench;
|
|
bench.batch(kNumKeys);
|
|
|
|
const int64_t beginBytes = __builtin_bswap64(0);
|
|
const int64_t endBytes = __builtin_bswap64(kNumKeys);
|
|
const String begin{(const uint8_t *)&beginBytes, 8};
|
|
const String end{(const uint8_t *)&endBytes, 8};
|
|
|
|
// Insert clear in entire range, so that all reads are served from versioned,
|
|
// logically and hopefully physically.
|
|
{
|
|
weaselab::VersionedMap::Mutation mutations[] = {
|
|
{begin.data(), int(begin.size()), end.data(), int(end.size()),
|
|
weaselab::VersionedMap::Clear},
|
|
};
|
|
facade.addMutations(mutations, sizeof(mutations) / sizeof(mutations[0]),
|
|
facade.getVersion() + 1);
|
|
}
|
|
|
|
// Add keys
|
|
for (int i = 0; i < kNumKeys; ++i) {
|
|
const int64_t k = __builtin_bswap64(i);
|
|
weaselab::VersionedMap::Mutation mutations[] = {
|
|
{(const uint8_t *)&k, 8, (const uint8_t *)&k, 8,
|
|
weaselab::VersionedMap::Set},
|
|
};
|
|
facade.addMutations(mutations, sizeof(mutations) / sizeof(mutations[0]),
|
|
facade.getVersion() + 1);
|
|
}
|
|
|
|
// Populate the unversioned map
|
|
for (int i = 0; i < kNumKeys; ++i) {
|
|
const int64_t k = __builtin_bswap64(i);
|
|
weaselab::VersionedMap::Mutation mutations[] = {
|
|
{(const uint8_t *)&k, 8, (const uint8_t *)&k, 8,
|
|
weaselab::VersionedMap::Set},
|
|
};
|
|
facade.addMutations(mutations, sizeof(mutations) / sizeof(mutations[0]),
|
|
facade.getVersion() + 1);
|
|
}
|
|
facade.setOldestVersion(facade.getVersion() - 1, /*force*/ true);
|
|
|
|
bench.run("Facade versioned-only read forward", [&]() {
|
|
facade.viewAt(facade.getVersion()).rangeRead(begin, end, kNumKeys, false);
|
|
});
|
|
|
|
bench.run("Facade versioned-only read reverse", [&]() {
|
|
facade.viewAt(facade.getVersion()).rangeRead(begin, end, kNumKeys, true);
|
|
});
|
|
}
|
|
|
|
int main() {
|
|
monotonicallyIncreasing();
|
|
bulkFirstGeq();
|
|
facadeVersionedOnlyRead();
|
|
}
|