"max of max" for Node48

This commit is contained in:
2024-06-26 17:54:03 -07:00
parent 23ace8aac5
commit 6520e3d734

View File

@@ -294,6 +294,8 @@ struct Node48 : Node {
int8_t nextFree; int8_t nextFree;
int8_t index[256]; int8_t index[256];
Child children[kMaxNodes]; Child children[kMaxNodes];
// Max of each "page" of 16 children
int64_t maxOfMax[16];
uint8_t *partialKey() { return (uint8_t *)(this + 1); } uint8_t *partialKey() { return (uint8_t *)(this + 1); }
@@ -417,6 +419,7 @@ inline void Node48::copyChildrenAndKeyFrom(const Node16 &other) {
children[i] = other.children[i]; children[i] = other.children[i];
assert(children[i].child->parent == &other); assert(children[i].child->parent == &other);
children[i].child->parent = this; children[i].child->parent = this;
maxOfMax[x >> 4] = std::max(maxOfMax[x >> 4], children[i].childMaxVersion);
++i; ++i;
} }
} }
@@ -431,6 +434,7 @@ inline void Node48::copyChildrenAndKeyFrom(const Node48 &other) {
assert(children[i].child->parent == &other); assert(children[i].child->parent == &other);
children[i].child->parent = this; children[i].child->parent = this;
} }
memcpy(maxOfMax, other.maxOfMax, sizeof(maxOfMax));
memcpy(partialKey(), &other + 1, partialKeyLen); memcpy(partialKey(), &other + 1, partialKeyLen);
} }
@@ -453,6 +457,7 @@ inline void Node48::copyChildrenAndKeyFrom(const Node256 &other) {
++i; ++i;
}, },
0, 256); 0, 256);
memcpy(maxOfMax, other.maxOfMax, sizeof(maxOfMax));
memcpy(partialKey(), &other + 1, partialKeyLen); memcpy(partialKey(), &other + 1, partialKeyLen);
} }
@@ -467,10 +472,9 @@ inline void Node256::copyChildrenAndKeyFrom(const Node48 &other) {
children[c] = other.children[other.index[c]]; children[c] = other.children[other.index[c]];
assert(children[c].child->parent == &other); assert(children[c].child->parent == &other);
children[c].child->parent = this; children[c].child->parent = this;
maxOfMax[c >> 4] =
std::max(maxOfMax[c >> 4], children[c].childMaxVersion);
}, },
0, 256); 0, 256);
memcpy(maxOfMax, other.maxOfMax, sizeof(maxOfMax));
memcpy(partialKey(), &other + 1, partialKeyLen); memcpy(partialKey(), &other + 1, partialKeyLen);
} }
@@ -571,7 +575,7 @@ template <class T> struct BoundedFreeListAllocator {
if constexpr (!std::is_same_v<T, Node0>) { if constexpr (!std::is_same_v<T, Node0>) {
memset(result->children, 0, sizeof(result->children)); memset(result->children, 0, sizeof(result->children));
} }
if constexpr (std::is_same_v<T, Node256>) { if constexpr (std::is_same_v<T, Node48> || std::is_same_v<T, Node256>) {
memset(result->maxOfMax, 0, sizeof(result->maxOfMax)); memset(result->maxOfMax, 0, sizeof(result->maxOfMax));
} }
return result; return result;
@@ -1688,13 +1692,37 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end,
} break; } break;
case Type_Node48: { case Type_Node48: {
auto *self = static_cast<Node48 *>(n); auto *self = static_cast<Node48 *>(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;
}
}
// 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; bool result = true;
self->bitSet.forEachInRange( for (int i = (begin >> 4) + 1; i < (end - 1) >> 4; ++i) {
[&](int i) { result &= self->maxOfMax[i] <= readVersion;
result &= }
self->children[self->index[i]].childMaxVersion <= readVersion;
},
begin, end);
return result; return result;
} }
case Type_Node256: { case Type_Node256: {
@@ -2656,6 +2684,7 @@ void setMaxVersion(Node *n, ConflictSet::Impl *impl, int64_t newMax) {
auto *n48 = static_cast<Node48 *>(n); auto *n48 = static_cast<Node48 *>(n);
assert(n48->bitSet.test(index)); assert(n48->bitSet.test(index));
n48->children[n48->index[index]].childMaxVersion = newMax; n48->children[n48->index[index]].childMaxVersion = newMax;
n48->maxOfMax[index >> 4] = std::max(n48->maxOfMax[index >> 4], newMax);
return; return;
} }
case Type_Node256: { case Type_Node256: {