From c882d7663de9f90084fe95d455d4aae395d41f88 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Wed, 26 Jun 2024 18:57:08 -0700 Subject: [PATCH] Maintain "reverseIndex" in Node48 --- ConflictSet.cpp | 60 ++++++++++++++++++------------------------------- 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 074cf2d..a5404bd 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -294,8 +294,7 @@ struct Node48 : Node { int8_t nextFree; int8_t index[256]; Child children[kMaxNodes]; - // Max of each "page" of 16 children - int64_t maxOfMax[16]; + uint8_t reverseIndex[kMaxNodes]; uint8_t *partialKey() { return (uint8_t *)(this + 1); } @@ -419,7 +418,7 @@ inline void Node48::copyChildrenAndKeyFrom(const Node16 &other) { children[i] = other.children[i]; assert(children[i].child->parent == &other); children[i].child->parent = this; - maxOfMax[x >> 4] = std::max(maxOfMax[x >> 4], children[i].childMaxVersion); + reverseIndex[i] = x; ++i; } } @@ -434,7 +433,7 @@ inline void Node48::copyChildrenAndKeyFrom(const Node48 &other) { assert(children[i].child->parent == &other); children[i].child->parent = this; } - memcpy(maxOfMax, other.maxOfMax, sizeof(maxOfMax)); + memcpy(reverseIndex, other.reverseIndex, sizeof(reverseIndex)); memcpy(partialKey(), &other + 1, partialKeyLen); } @@ -454,10 +453,10 @@ inline void Node48::copyChildrenAndKeyFrom(const Node256 &other) { children[i] = other.children[c]; assert(children[i].child->parent == &other); children[i].child->parent = this; + reverseIndex[i] = c; ++i; }, 0, 256); - memcpy(maxOfMax, other.maxOfMax, sizeof(maxOfMax)); memcpy(partialKey(), &other + 1, partialKeyLen); } @@ -472,9 +471,10 @@ inline void Node256::copyChildrenAndKeyFrom(const Node48 &other) { children[c] = other.children[other.index[c]]; assert(children[c].child->parent == &other); children[c].child->parent = this; + maxOfMax[c >> 4] = + std::max(maxOfMax[c >> 4], children[c].childMaxVersion); }, 0, 256); - memcpy(maxOfMax, other.maxOfMax, sizeof(maxOfMax)); memcpy(partialKey(), &other + 1, partialKeyLen); } @@ -575,7 +575,7 @@ template struct BoundedFreeListAllocator { if constexpr (!std::is_same_v) { memset(result->children, 0, sizeof(result->children)); } - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (std::is_same_v) { memset(result->maxOfMax, 0, sizeof(result->maxOfMax)); } return result; @@ -1047,6 +1047,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, assert(self48->nextFree < 48); int nextFree = self48->nextFree++; self48->index[index] = nextFree; + self48->reverseIndex[nextFree] = index; auto &result = self48->children[nextFree].child; result = nullptr; return result; @@ -1346,8 +1347,10 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl, if (toRemoveChildrenIndex != lastChildrenIndex) { parent48->children[toRemoveChildrenIndex] = parent48->children[lastChildrenIndex]; - parent48->index[parent48->children[toRemoveChildrenIndex] - .child->parentsIndex] = toRemoveChildrenIndex; + auto parentIndex = + parent48->children[toRemoveChildrenIndex].child->parentsIndex; + parent48->index[parentIndex] = toRemoveChildrenIndex; + parent48->reverseIndex[toRemoveChildrenIndex] = parentIndex; } --parent->numChildren; @@ -1692,36 +1695,18 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end, } break; case Type_Node48: { auto *self = static_cast(n); - // Check the first page - if (self->maxOfMax[begin >> 4] > readVersion) { - bool result = true; - self->bitSet.forEachInRange( - [&](int i) { - result &= - self->children[self->index[i]].childMaxVersion <= readVersion; - }, - begin, std::min((begin & ~15) + 16, end)); - if (!result) { - return result; - } + bool conflict[Node48::kMaxNodes] = {}; + assume(self->numChildren >= kMinChildrenNode48 - 1 /* entry present */); + assume(self->numChildren <= Node48::kMaxNodes); + for (int i = 0; i < self->numChildren; ++i) { + assert(self->index[self->reverseIndex[i]] == i); + conflict[i] = (begin <= self->reverseIndex[i]) & + (self->reverseIndex[i] < end) & + (self->children[i].childMaxVersion > readVersion); } - // Check the last page - if (end >= 1 && self->maxOfMax[(end - 1) >> 4] > readVersion) { - bool result = true; - self->bitSet.forEachInRange( - [&](int i) { - result &= - self->children[self->index[i]].childMaxVersion <= readVersion; - }, - std::max(begin, end & ~15), end); - if (!result) { - return result; - } - } - // Check inner pages bool result = true; - for (int i = (begin >> 4) + 1; i < (end - 1) >> 4; ++i) { - result &= self->maxOfMax[i] <= readVersion; + for (auto c : conflict) { + result &= !c; } return result; } @@ -2685,7 +2670,6 @@ void setMaxVersion(Node *n, ConflictSet::Impl *impl, int64_t newMax) { auto *n48 = static_cast(n); assert(n48->bitSet.test(index)); n48->children[n48->index[index]].childMaxVersion = newMax; - n48->maxOfMax[index >> 4] = std::max(n48->maxOfMax[index >> 4], newMax); return; } case Type_Node256: {