Avoid some branches on node type while inserting
Some checks failed
weaselab/conflict-set/pipeline/head There was a failure building this commit
Some checks failed
weaselab/conflict-set/pipeline/head There was a failure building this commit
This commit is contained in:
@@ -1125,8 +1125,10 @@ Node *getFirstChildExists(Node *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Caller is responsible for assigning a non-null pointer to the returned
|
// Caller is responsible for assigning a non-null pointer to the returned
|
||||||
// reference if null
|
// reference if null. Updates child's max version to `newMaxVersion` if child
|
||||||
Node *&getOrCreateChild(Node *&self, uint8_t index, WriteContext *tls) {
|
// exists but does not have a partial key.
|
||||||
|
Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||||
|
InternalVersionT newMaxVersion, WriteContext *tls) {
|
||||||
|
|
||||||
// Fast path for if it exists already
|
// Fast path for if it exists already
|
||||||
switch (self->getType()) {
|
switch (self->getType()) {
|
||||||
@@ -1136,6 +1138,9 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, WriteContext *tls) {
|
|||||||
auto *self3 = static_cast<Node3 *>(self);
|
auto *self3 = static_cast<Node3 *>(self);
|
||||||
int i = getNodeIndex(self3, index);
|
int i = getNodeIndex(self3, index);
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
|
if (self3->children[i]->partialKeyLen == 0) {
|
||||||
|
self3->childMaxVersion[i] = newMaxVersion;
|
||||||
|
}
|
||||||
return self3->children[i];
|
return self3->children[i];
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -1143,6 +1148,9 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, WriteContext *tls) {
|
|||||||
auto *self16 = static_cast<Node16 *>(self);
|
auto *self16 = static_cast<Node16 *>(self);
|
||||||
int i = getNodeIndex(self16, index);
|
int i = getNodeIndex(self16, index);
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
|
if (self16->children[i]->partialKeyLen == 0) {
|
||||||
|
self16->childMaxVersion[i] = newMaxVersion;
|
||||||
|
}
|
||||||
return self16->children[i];
|
return self16->children[i];
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -1150,12 +1158,23 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, WriteContext *tls) {
|
|||||||
auto *self48 = static_cast<Node48 *>(self);
|
auto *self48 = static_cast<Node48 *>(self);
|
||||||
int secondIndex = self48->index[index];
|
int secondIndex = self48->index[index];
|
||||||
if (secondIndex >= 0) {
|
if (secondIndex >= 0) {
|
||||||
|
if (self48->children[secondIndex]->partialKeyLen == 0) {
|
||||||
|
self48->childMaxVersion[secondIndex] = newMaxVersion;
|
||||||
|
self48->maxOfMax[secondIndex >> Node48::kMaxOfMaxShift] =
|
||||||
|
std::max(self48->maxOfMax[secondIndex >> Node48::kMaxOfMaxShift],
|
||||||
|
newMaxVersion);
|
||||||
|
}
|
||||||
return self48->children[secondIndex];
|
return self48->children[secondIndex];
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Type_Node256: {
|
case Type_Node256: {
|
||||||
auto *self256 = static_cast<Node256 *>(self);
|
auto *self256 = static_cast<Node256 *>(self);
|
||||||
if (auto &result = self256->children[index]; result != nullptr) {
|
if (auto &result = self256->children[index]; result != nullptr) {
|
||||||
|
if (self256->children[index]->partialKeyLen == 0) {
|
||||||
|
self256->childMaxVersion[index] = newMaxVersion;
|
||||||
|
self256->maxOfMax[index >> Node256::kMaxOfMaxShift] = std::max(
|
||||||
|
self256->maxOfMax[index >> Node256::kMaxOfMaxShift], newMaxVersion);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -2883,13 +2902,12 @@ checkMaxBetweenExclusiveImpl<true>(Node *n, int begin, int end,
|
|||||||
InternalVersionT readVersion, ReadContext *);
|
InternalVersionT readVersion, ReadContext *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Consume the partial key of `self` if it exists, and update `self` and `key`
|
// Consume the partial key of `self` (which must exist), and update `self` and
|
||||||
// such that `self` is along the search path of `key`, and has maxVersion
|
// `key` such that `self` is along the search path of `key`
|
||||||
// `writeVersion`
|
|
||||||
void consumePartialKey(Node *&self, std::span<const uint8_t> &key,
|
void consumePartialKey(Node *&self, std::span<const uint8_t> &key,
|
||||||
InternalVersionT writeVersion, WriteContext *tls,
|
InternalVersionT writeVersion, WriteContext *tls,
|
||||||
ConflictSet::Impl *impl) {
|
ConflictSet::Impl *impl) {
|
||||||
if (self->partialKeyLen > 0) {
|
assert(self->partialKeyLen > 0);
|
||||||
// Handle an existing partial key
|
// Handle an existing partial key
|
||||||
int commonLen = std::min<int>(self->partialKeyLen, key.size());
|
int commonLen = std::min<int>(self->partialKeyLen, key.size());
|
||||||
int partialKeyIndex =
|
int partialKeyIndex =
|
||||||
@@ -2927,7 +2945,6 @@ void consumePartialKey(Node *&self, std::span<const uint8_t> &key,
|
|||||||
// up.
|
// up.
|
||||||
}
|
}
|
||||||
key = key.subspan(partialKeyIndex, key.size() - partialKeyIndex);
|
key = key.subspan(partialKeyIndex, key.size() - partialKeyIndex);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a pointer to the newly inserted node. Caller must set
|
// Returns a pointer to the newly inserted node. Caller must set
|
||||||
@@ -2939,18 +2956,19 @@ Node *insert(Node **self, std::span<const uint8_t> key,
|
|||||||
InternalVersionT writeVersion, WriteContext *tls,
|
InternalVersionT writeVersion, WriteContext *tls,
|
||||||
ConflictSet::Impl *impl) {
|
ConflictSet::Impl *impl) {
|
||||||
|
|
||||||
for (;; ++tls->accum.insert_iterations) {
|
if ((*self)->partialKeyLen > 0) {
|
||||||
|
|
||||||
consumePartialKey(*self, key, writeVersion, tls, impl);
|
consumePartialKey(*self, key, writeVersion, tls, impl);
|
||||||
|
}
|
||||||
assert(maxVersion(*self, impl) <= writeVersion);
|
assert(maxVersion(*self, impl) <= writeVersion);
|
||||||
setMaxVersion(*self, impl, writeVersion);
|
setMaxVersion(*self, impl, writeVersion);
|
||||||
|
|
||||||
|
for (;; ++tls->accum.insert_iterations) {
|
||||||
|
|
||||||
if (key.size() == 0) {
|
if (key.size() == 0) {
|
||||||
return *self;
|
return *self;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &child = getOrCreateChild(*self, key.front(), tls);
|
auto &child = getOrCreateChild(*self, key.front(), writeVersion, tls);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
child = tls->allocate<Node0>(key.size() - 1);
|
child = tls->allocate<Node0>(key.size() - 1);
|
||||||
child->numChildren = 0;
|
child->numChildren = 0;
|
||||||
@@ -2965,6 +2983,12 @@ Node *insert(Node **self, std::span<const uint8_t> key,
|
|||||||
|
|
||||||
self = &child;
|
self = &child;
|
||||||
key = key.subspan(1, key.size() - 1);
|
key = key.subspan(1, key.size() - 1);
|
||||||
|
|
||||||
|
if ((*self)->partialKeyLen > 0) {
|
||||||
|
consumePartialKey(*self, key, writeVersion, tls, impl);
|
||||||
|
assert(maxVersion(*self, impl) <= writeVersion);
|
||||||
|
setMaxVersion(*self, impl, writeVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user