From e024cb829181acb322a63ec60fbe40b7763c81f9 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Tue, 13 Aug 2024 10:28:29 -0700 Subject: [PATCH] Track entriesErased in destroyTree --- Bench.cpp | 16 +++++++++++++++- ConflictSet.cpp | 36 ++++++++++++++++++++++++++++-------- Internal.h | 10 ++++++++++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Bench.cpp b/Bench.cpp index 65da971..c2b76c6 100644 --- a/Bench.cpp +++ b/Bench.cpp @@ -361,7 +361,21 @@ void benchWorstCaseForRadixRangeRead() { void benchCreateAndDestroy() { ankerl::nanobench::Bench bench; - bench.run("create and destroy", [&]() { ConflictSet cs{0}; }); + bench.run("create and destroy", [&]() { + ConflictSet cs{0}; + ConflictSet::WriteRange w; + uint8_t b[9]; + b[8] = 0; + for (int64_t i = 0; i < 1000; i += 7) { + auto x = __builtin_bswap64(i); + memcpy(b, &x, 8); + w.begin.p = b; + w.begin.len = 8; + w.end.len = 0; + w.end.p = b; + cs.addWrites(&w, 1, 1); + } + }); } int main(void) { diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 7078e58..b563d34 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -2812,7 +2812,7 @@ Node **insert(Node **self, std::span key, return self; } -void destroyTree(Node *root) { +void destroyTree(Node *root, int64_t *entriesErased) { Arena arena; auto toFree = vector(arena); toFree.push_back(root); @@ -2827,11 +2827,31 @@ void destroyTree(Node *root) { while (toFree.size() > 0) { auto *n = toFree.back(); toFree.pop_back(); - // Add all children to toFree - for (auto c = getChildGeq(n, 0); c != nullptr; - c = getChildGeq(n, c->parentsIndex + 1)) { - assert(c != nullptr); - toFree.push_back(c); + *entriesErased += n->entryPresent; + + switch (n->getType()) { + case Type_Node0: { + } break; + case Type_Node3: { + auto *n3 = static_cast(n); + toFree.append(std::span(n3->children, n3->numChildren)); + } break; + case Type_Node16: { + auto *n16 = static_cast(n); + toFree.append(std::span(n16->children, n16->numChildren)); + } break; + case Type_Node48: { + auto *n48 = static_cast(n); + toFree.append(std::span(n48->children, n48->numChildren)); + } break; + case Type_Node256: { + auto *n256 = static_cast(n); + auto *out = toFree.unsafePrepareAppend(n256->numChildren).data(); + n256->bitSet.forEachSet([&](int i) { *out++ = n256->children[i]; }); + assert(out == toFree.end()); + } break; + default: // GCOVR_EXCL_LINE + __builtin_unreachable(); // GCOVR_EXCL_LINE } safe_free(n, n->size()); } @@ -3070,7 +3090,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { if (oldestExtantVersion < writeVersion - kMaxCorrectVersionWindow) [[unlikely]] { if (writeVersion > newestVersionFullPrecision + kNominalVersionWindow) { - destroyTree(root); + destroyTree(root, &tls.accum.entries_erased); init(writeVersion - kNominalVersionWindow); } @@ -3238,7 +3258,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { initMetrics(); } ~Impl() { - destroyTree(root); + destroyTree(root, &tls.accum.entries_erased); safe_free(metrics, metricsCount * sizeof(metrics[0])); } diff --git a/Internal.h b/Internal.h index 10ddf17..e90312a 100644 --- a/Internal.h +++ b/Internal.h @@ -273,6 +273,16 @@ template struct Vector { size_ += slice.size(); } + // Caller must write to the returned slice + std::span unsafePrepareAppend(int appendSize) { + if (size_ + appendSize > capacity) { + grow(std::max(size_ + appendSize, capacity * 2)); + } + auto result = std::span(t + size_, appendSize); + size_ += appendSize; + return result; + } + void push_back(const T &t) { append(std::span(&t, 1)); } T *begin() { return t; }