Node1 -> Node0

This commit is contained in:
2024-03-08 12:07:24 -08:00
parent 987e93b190
commit 02afd47d8f

View File

@@ -220,7 +220,7 @@ int BitSet::firstSetGeq(int i) const {
} }
enum class Type : int8_t { enum class Type : int8_t {
Node1, Node0,
Node4, Node4,
Node16, Node16,
Node48, Node48,
@@ -249,6 +249,9 @@ struct Node {
/* end section that's copied to the next node */ /* end section that's copied to the next node */
}; };
constexpr int kNodeCopyBegin = offsetof(Node, entryPresent);
constexpr int kNodeCopySize = sizeof(Node) - kNodeCopyBegin;
static_assert(offsetof(Node, entry) == static_assert(offsetof(Node, entry) ==
offsetof(Node, partialKey) + kPartialKeyMaxLenEntryPresent); offsetof(Node, partialKey) + kPartialKeyMaxLenEntryPresent);
static_assert(std::is_trivial_v<Entry>); static_assert(std::is_trivial_v<Entry>);
@@ -258,12 +261,11 @@ struct Child {
Node *child; Node *child;
}; };
struct Node1 : Node { struct Node0 : Node {
// Sorted // Sorted
uint8_t index[16]; // 16 so that we can use the same simd index search uint8_t index[16]; // 16 so that we can use the same simd index search
// implementation as Node16 // implementation as Node16
Child children[1]; Node0() { this->type = Type::Node0; }
Node1() { this->type = Type::Node1; }
}; };
struct Node4 : Node { struct Node4 : Node {
@@ -304,7 +306,7 @@ struct Node256 : Node {
}; };
struct NodeAllocators { struct NodeAllocators {
BoundedFreeListAllocator<Node1> node1; BoundedFreeListAllocator<Node0> node0;
BoundedFreeListAllocator<Node4> node4; BoundedFreeListAllocator<Node4> node4;
BoundedFreeListAllocator<Node16> node16; BoundedFreeListAllocator<Node16> node16;
BoundedFreeListAllocator<Node48> node48; BoundedFreeListAllocator<Node48> node48;
@@ -540,19 +542,14 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
} }
} }
if (self->type == Type::Node1) { if (self->type == Type::Node0) {
auto *self1 = static_cast<Node1 *>(self); auto *self0 = static_cast<Node0 *>(self);
if (self->numChildren == 1) { auto *newSelf = allocators->node4.allocate();
auto *newSelf = allocators->node4.allocate(); memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
memcpy((void *)newSelf, self, sizeof(Node1)); kNodeCopySize);
newSelf->type = Type::Node4; allocators->node0.release(self0);
allocators->node1.release(self1); self = newSelf;
setChildrenParents(newSelf);
self = newSelf;
} else {
assert(self->numChildren == 0);
}
goto insert16; goto insert16;
@@ -561,8 +558,10 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
if (self->numChildren == 4) { if (self->numChildren == 4) {
auto *newSelf = allocators->node16.allocate(); auto *newSelf = allocators->node16.allocate();
memcpy((void *)newSelf, self, sizeof(Node4)); memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
newSelf->type = Type::Node16; kNodeCopySize);
memcpy((void *)newSelf->index, (void *)self4->index,
sizeof(self4->index) + sizeof(self4->children));
allocators->node4.release(self4); allocators->node4.release(self4);
setChildrenParents(newSelf); setChildrenParents(newSelf);
self = newSelf; self = newSelf;
@@ -575,9 +574,8 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
if (self->numChildren == 16) { if (self->numChildren == 16) {
auto *self16 = static_cast<Node16 *>(self); auto *self16 = static_cast<Node16 *>(self);
auto *newSelf = allocators->node48.allocate(); auto *newSelf = allocators->node48.allocate();
memcpy((char *)newSelf + sizeof(Node::type), memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
(char *)self + sizeof(Node::type), kNodeCopySize);
sizeof(Node) - sizeof(Node::type));
newSelf->nextFree = 16; newSelf->nextFree = 16;
int i = 0; int i = 0;
for (auto x : self16->index) { for (auto x : self16->index) {
@@ -616,9 +614,8 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
if (self->numChildren == 48) { if (self->numChildren == 48) {
auto *self48 = static_cast<Node48 *>(self); auto *self48 = static_cast<Node48 *>(self);
auto *newSelf = allocators->node256.allocate(); auto *newSelf = allocators->node256.allocate();
memcpy((char *)newSelf + sizeof(Node::type), memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
(char *)self + sizeof(Node::type), kNodeCopySize);
sizeof(Node) - sizeof(Node::type));
newSelf->bitSet = self48->bitSet; newSelf->bitSet = self48->bitSet;
newSelf->bitSet.forEachInRange( newSelf->bitSet.forEachInRange(
[&](int i) { [&](int i) {
@@ -655,8 +652,8 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) { void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) {
auto *child = getChildExists(self, index); auto *child = getChildExists(self, index);
switch (child->type) { switch (child->type) {
case Type::Node1: case Type::Node0:
allocators->node1.release((Node1 *)child); allocators->node0.release((Node0 *)child);
break; break;
case Type::Node4: case Type::Node4:
allocators->node4.release((Node4 *)child); allocators->node4.release((Node4 *)child);
@@ -1045,7 +1042,7 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) {
} }
} }
switch (n->type) { switch (n->type) {
case Type::Node1: case Type::Node0:
[[fallthrough]]; [[fallthrough]];
case Type::Node4: case Type::Node4:
[[fallthrough]]; [[fallthrough]];
@@ -1553,7 +1550,7 @@ template <bool kBegin>
auto *old = *self; auto *old = *self;
int64_t oldMaxVersion = maxVersion(old, impl); int64_t oldMaxVersion = maxVersion(old, impl);
*self = allocators->node1.allocate(); *self = allocators->node0.allocate();
memcpy((char *)*self + sizeof(Node::type), memcpy((char *)*self + sizeof(Node::type),
(char *)old + sizeof(Node::type), (char *)old + sizeof(Node::type),
@@ -1607,7 +1604,7 @@ template <bool kBegin>
auto &child = getOrCreateChild(*self, key.front(), allocators); auto &child = getOrCreateChild(*self, key.front(), allocators);
if (!child) { if (!child) {
child = allocators->node1.allocate(); child = allocators->node0.allocate();
child->parent = *self; child->parent = *self;
child->parentsIndex = key.front(); child->parentsIndex = key.front();
maxVersion(child, impl) = maxVersion(child, impl) =
@@ -1889,7 +1886,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
explicit Impl(int64_t oldestVersion) : oldestVersion(oldestVersion) { explicit Impl(int64_t oldestVersion) : oldestVersion(oldestVersion) {
// Insert "" // Insert ""
root = allocators.node1.allocate(); root = allocators.node0.allocate();
rootMaxVersion = oldestVersion; rootMaxVersion = oldestVersion;
root->entry.pointVersion = oldestVersion; root->entry.pointVersion = oldestVersion;
root->entry.rangeVersion = oldestVersion; root->entry.rangeVersion = oldestVersion;
@@ -1962,8 +1959,8 @@ ConflictSet::~ConflictSet() {
__attribute__((visibility("default"))) void showMemory(const ConflictSet &cs) { __attribute__((visibility("default"))) void showMemory(const ConflictSet &cs) {
ConflictSet::Impl *impl; ConflictSet::Impl *impl;
memcpy(&impl, &cs, sizeof(impl)); // NOLINT memcpy(&impl, &cs, sizeof(impl)); // NOLINT
fprintf(stderr, "Max Node1 memory usage: %" PRId64 "\n", fprintf(stderr, "Max Node0 memory usage: %" PRId64 "\n",
impl->allocators.node1.highWaterMarkBytes()); impl->allocators.node0.highWaterMarkBytes());
fprintf(stderr, "Max Node4 memory usage: %" PRId64 "\n", fprintf(stderr, "Max Node4 memory usage: %" PRId64 "\n",
impl->allocators.node4.highWaterMarkBytes()); impl->allocators.node4.highWaterMarkBytes());
fprintf(stderr, "Max Node16 memory usage: %" PRId64 "\n", fprintf(stderr, "Max Node16 memory usage: %" PRId64 "\n",
@@ -2251,7 +2248,7 @@ int main(void) {
ConflictSet::Impl cs{0}; ConflictSet::Impl cs{0};
for (int j = 0; j < 256; ++j) { for (int j = 0; j < 256; ++j) {
getOrCreateChild(cs.root, j, &cs.allocators) = getOrCreateChild(cs.root, j, &cs.allocators) =
cs.allocators.node1.allocate(); cs.allocators.node0.allocate();
if (j % 10 == 0) { if (j % 10 == 0) {
bench.run("MaxExclusive " + std::to_string(j), [&]() { bench.run("MaxExclusive " + std::to_string(j), [&]() {
bench.doNotOptimizeAway(maxBetweenExclusive(cs.root, 0, 256)); bench.doNotOptimizeAway(maxBetweenExclusive(cs.root, 0, 256));