Track entriesErased in destroyTree

This commit is contained in:
2024-08-13 10:28:29 -07:00
parent 0740dcad43
commit e024cb8291
3 changed files with 53 additions and 9 deletions

View File

@@ -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) {

View File

@@ -2812,7 +2812,7 @@ Node **insert(Node **self, std::span<const uint8_t> key,
return self;
}
void destroyTree(Node *root) {
void destroyTree(Node *root, int64_t *entriesErased) {
Arena arena;
auto toFree = vector<Node *>(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<Node3 *>(n);
toFree.append(std::span<Node *>(n3->children, n3->numChildren));
} break;
case Type_Node16: {
auto *n16 = static_cast<Node16 *>(n);
toFree.append(std::span<Node *>(n16->children, n16->numChildren));
} break;
case Type_Node48: {
auto *n48 = static_cast<Node48 *>(n);
toFree.append(std::span<Node *>(n48->children, n48->numChildren));
} break;
case Type_Node256: {
auto *n256 = static_cast<Node256 *>(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]));
}

View File

@@ -273,6 +273,16 @@ template <class T> struct Vector {
size_ += slice.size();
}
// Caller must write to the returned slice
std::span<T> unsafePrepareAppend(int appendSize) {
if (size_ + appendSize > capacity) {
grow(std::max<int>(size_ + appendSize, capacity * 2));
}
auto result = std::span<T>(t + size_, appendSize);
size_ += appendSize;
return result;
}
void push_back(const T &t) { append(std::span<const T>(&t, 1)); }
T *begin() { return t; }