WIP downsize for Node{16,48,256} on erase

CC #9
This commit is contained in:
2024-03-11 12:06:45 -07:00
parent 6e212847ac
commit 13ee3c3a12

View File

@@ -552,6 +552,12 @@ int getChildGeq(Node *self, int child) {
return -1;
}
void setChildrenParents(Node4 *n) {
for (int i = 0; i < n->numChildren; ++i) {
n->children[i].child->parent = n;
}
}
void setChildrenParents(Node16 *n) {
for (int i = 0; i < n->numChildren; ++i) {
n->children[i].child->parent = n;
@@ -706,8 +712,95 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
}
}
// TODO fuse into erase child so we don't need to repeat branches on type
void maybeDownsize(Node *self, Node *&root, NodeAllocators *allocators) {
switch (self->type) {
case Type::Node0:
__builtin_unreachable(); // GCOVR_EXCL_LINE
case Type::Node4:
if (self->numChildren < kMinChildrenNode4) {
// Merge partial key with child
}
break;
case Type::Node16:
if (self->numChildren < kMinChildrenNode16) {
auto *self16 = (Node16 *)self;
auto *newSelf = allocators->node4.allocate(self->partialKeyLen);
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
kNodeCopySize);
memcpy(newSelf->partialKey(), self16->partialKey(), self->partialKeyLen);
// TODO replace with memcpy?
for (int i = 0; i < 4; ++i) {
newSelf->index[i] = self16->index[i];
newSelf->children[i] = self16->children[i];
}
allocators->node16.release(self16);
setChildrenParents(newSelf);
if (newSelf->parent == nullptr) {
root = newSelf;
} else {
getChildExists(newSelf->parent, newSelf->parentsIndex) = newSelf;
}
}
break;
case Type::Node48:
if (self->numChildren < kMinChildrenNode48) {
auto *self48 = (Node48 *)self;
auto *newSelf = allocators->node16.allocate(self->partialKeyLen);
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
kNodeCopySize);
memcpy(newSelf->partialKey(), self48->partialKey(), self->partialKeyLen);
int i = 0;
self48->bitSet.forEachInRange(
[&](int c) {
newSelf->index[i] = c;
newSelf->children[i] = self48->children[self48->index[c]];
++i;
},
0, 256);
allocators->node48.release(self48);
setChildrenParents(newSelf);
if (newSelf->parent == nullptr) {
root = newSelf;
} else {
getChildExists(newSelf->parent, newSelf->parentsIndex) = newSelf;
}
}
break;
case Type::Node256:
if (self->numChildren < kMinChildrenNode256) {
auto *self256 = (Node256 *)self;
auto *newSelf = allocators->node48.allocate(self->partialKeyLen);
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
kNodeCopySize);
memcpy(newSelf->partialKey(), self256->partialKey(), self->partialKeyLen);
newSelf->bitSet = self256->bitSet;
newSelf->bitSet.forEachInRange(
[&](int c) {
newSelf->index[c] = newSelf->nextFree;
newSelf->children[newSelf->nextFree] = self256->children[c];
++newSelf->nextFree;
},
0, 256);
allocators->node256.release(self256);
setChildrenParents(newSelf);
if (newSelf->parent == nullptr) {
root = newSelf;
} else {
getChildExists(newSelf->parent, newSelf->parentsIndex) = newSelf;
}
}
break;
}
}
// Precondition - an entry for index must exist in the node
void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) {
void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators,
Node *&root) {
auto *child = getChildExists(self, index);
switch (child->type) {
case Type::Node0:
@@ -733,7 +826,7 @@ void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) {
memmove(self16->index + nodeIndex, self16->index + nodeIndex + 1,
sizeof(self16->index[0]) * (self->numChildren - (nodeIndex + 1)));
memmove(self16->children + nodeIndex, self16->children + nodeIndex + 1,
sizeof(self16->children[0]) * // NOLINT
sizeof(self16->children[0]) *
(self->numChildren - (nodeIndex + 1)));
} else if (self->type == Type::Node48) {
auto *self48 = static_cast<Node48 *>(self);
@@ -757,7 +850,9 @@ void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) {
--self->numChildren;
if (self->numChildren == 0 && !self->entryPresent &&
self->parent != nullptr) {
eraseChild(self->parent, self->parentsIndex, allocators);
eraseChild(self->parent, self->parentsIndex, allocators, root);
} else {
maybeDownsize(self, root, allocators);
}
}
@@ -1773,7 +1868,7 @@ void addWriteRange(Node *&root, int64_t oldestVersion,
beginNode = nextLogical(beginNode);
old->entryPresent = false;
if (old->numChildren == 0 && old->parent != nullptr) {
eraseChild(old->parent, old->parentsIndex, allocators);
eraseChild(old->parent, old->parentsIndex, allocators, root);
}
}
}
@@ -1904,7 +1999,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
assert(n->entry.rangeVersion <= oldestVersion);
prev->entryPresent = false;
if (prev->numChildren == 0 && prev->parent != nullptr) {
eraseChild(prev->parent, prev->parentsIndex, &allocators);
eraseChild(prev->parent, prev->parentsIndex, &allocators, root);
}
}