From 3c9c5bd9fbf28088e1fb097d85b8197f0b12f39e Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Tue, 30 Jan 2024 13:08:01 -0800 Subject: [PATCH] Add benchmarks for getChild{L,G}eq --- .clangd | 2 +- CMakeLists.txt | 4 +-- ConflictSet.cpp | 79 ++++++++++++++++++++++++++++--------------------- 3 files changed, 49 insertions(+), 36 deletions(-) diff --git a/.clangd b/.clangd index 9be6873..61e5abe 100644 --- a/.clangd +++ b/.clangd @@ -1,2 +1,2 @@ CompileFlags: - Add: [-DENABLE_MAIN, -UNDEBUG, -DENABLE_FUZZ] + Add: [-DENABLE_MAIN, -UNDEBUG, -DENABLE_FUZZ, -fexceptions] diff --git a/CMakeLists.txt b/CMakeLists.txt index 4454194..05ece1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 3fab679..11a6f07 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -411,8 +411,7 @@ int getChildLeq(Node *self, int child) { #endif } else if (self->type == Type::Node48) { auto *self48 = static_cast(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 key, int64_t writeVersion) { } } +void destroyTree(Node *root) { + Arena arena; + auto toFree = vector(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(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)); }); + } + destroyTree(n); } - cs.addWrites(write, kNumKeys); - refImpl.addWrites(write, kNumKeys); - debugPrintDot(stdout, cs.root); + { + 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