Add benchmarks for getChild{L,G}eq

This commit is contained in:
2024-01-30 13:08:01 -08:00
parent 017cffd580
commit 3c9c5bd9fb
3 changed files with 49 additions and 36 deletions

View File

@@ -1,2 +1,2 @@
CompileFlags:
Add: [-DENABLE_MAIN, -UNDEBUG, -DENABLE_FUZZ]
Add: [-DENABLE_MAIN, -UNDEBUG, -DENABLE_FUZZ, -fexceptions]

View File

@@ -82,8 +82,8 @@ target_compile_definitions(conflict_set_main PRIVATE ENABLE_MAIN)
set(FUZZ_FLAGS "-fsanitize=fuzzer-no-link,address,undefined")
include(CheckCXXCompilerFlag)
cmake_push_check_state()
set(CMAKE_REQUIRED_LINK_OPTIONS -fsanitize=fuzzer)
check_cxx_compiler_flag(-fsanitize=fuzzer HAS_LIB_FUZZER)
set(CMAKE_REQUIRED_LINK_OPTIONS -fsanitize=fuzzer-no-link)
check_cxx_compiler_flag(-fsanitize=fuzzer-no-link HAS_LIB_FUZZER)
cmake_pop_check_state()
if(HAS_LIB_FUZZER)

View File

@@ -411,8 +411,7 @@ int getChildLeq(Node *self, int child) {
#endif
} else if (self->type == Type::Node48) {
auto *self48 = static_cast<Node48 *>(self);
// TODO the plain loop is faster?
#if 0 && (defined(HAS_AVX) || defined(HAS_ARM_NEON))
#if defined(HAS_AVX) || defined(HAS_ARM_NEON)
int i = child;
if (i < 0) {
return -1;
@@ -736,6 +735,24 @@ void insert(Node **self_, std::span<const uint8_t> key, int64_t writeVersion) {
}
}
void destroyTree(Node *root) {
Arena arena;
auto toFree = vector<Node *>(arena);
toFree.push_back(root);
while (toFree.size() > 0) {
auto *n = toFree.back();
toFree.pop_back();
// Add all children to toFree
for (int child = getChildGeq(n, 0); child >= 0;
child = getChildGeq(n, child + 1)) {
auto *c = getChildExists(n, child);
assert(c != nullptr);
toFree.push_back(c);
}
free(n);
}
}
struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
void check(const ReadRange *reads, Result *result, int count) const {
for (int i = 0; i < count; ++i) {
@@ -781,23 +798,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
root->entry.rangeVersion = oldestVersion;
root->entryPresent = true;
}
~Impl() {
Arena arena;
auto toFree = vector<Node *>(arena);
toFree.push_back(root);
while (toFree.size() > 0) {
auto *n = toFree.back();
toFree.pop_back();
// Add all children to toFree
for (int child = getChildGeq(n, 0); child >= 0;
child = getChildGeq(n, child + 1)) {
auto *c = getChildExists(n, child);
assert(c != nullptr);
toFree.push_back(c);
}
free(n);
}
}
~Impl() { destroyTree(root); }
Node *root;
int64_t oldestVersion;
@@ -991,21 +992,33 @@ void __throw_length_error(const char *) { __builtin_unreachable(); }
} // namespace std
#ifdef ENABLE_MAIN
int main(void) {
int64_t writeVersion = 0;
ConflictSet::Impl cs{writeVersion};
ReferenceImpl refImpl{writeVersion};
Arena arena;
constexpr int kNumKeys = 10;
auto *write = new (arena) ConflictSet::WriteRange[kNumKeys];
for (int i = 0; i < kNumKeys; ++i) {
write[i].begin = toKey(arena, i);
write[i].end.len = 0;
write[i].writeVersion = ++writeVersion;
#define ANKERL_NANOBENCH_IMPLEMENT
#include "third_party/nanobench.h"
void bench() {
ankerl::nanobench::Bench bench;
{
auto *n = newNode();
for (int i = 0; i < 64; ++i) {
getOrCreateChild(n, i) = newNode();
bench.run("getChildLeq" + std::to_string(i),
[&]() { bench.doNotOptimizeAway(getChildLeq(n, 255)); });
}
cs.addWrites(write, kNumKeys);
refImpl.addWrites(write, kNumKeys);
debugPrintDot(stdout, cs.root);
destroyTree(n);
}
{
auto *n = newNode();
for (int i = 255; i >= 3 * 64; --i) {
getOrCreateChild(n, i) = newNode();
bench.run("getChildGeq" + std::to_string(i),
[&]() { bench.doNotOptimizeAway(getChildGeq(n, 0)); });
}
destroyTree(n);
}
}
int main(void) {
bench();
return 0;
}
#endif