Short circuit point reads based on maxVersion
All checks were successful
Tests / Release [gcc] total: 337, passed: 337
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap: Reference build: <a href="https://jenkins.weaselab.dev/job/weaselab/job/conflict-set/job/main/5//gcc">weaselab » conflict-set » main #5</a>
Tests / Coverage total: 335, passed: 335
weaselab/conflict-set/pipeline/head This commit looks good

This commit is contained in:
2024-02-06 14:38:39 -08:00
parent 68239cd80b
commit 9a80c96533
392 changed files with 88 additions and 24 deletions

View File

@@ -602,20 +602,6 @@ Node *prevPhysical(Node *node) {
}
}
Node *nextSibling(Node *node) {
for (;;) {
if (node->parent == nullptr) {
return nullptr;
}
auto next = getChildGeq(node->parent, node->parentsIndex + 1);
if (next < 0) {
node = node->parent;
} else {
return getChildExists(node->parent, next);
}
}
}
Node *prevLogical(Node *node) {
for (node = prevPhysical(node); node != nullptr && !node->entryPresent;
node = prevPhysical(node))
@@ -724,6 +710,88 @@ downLeftSpine:
}
}
// Logically this is the same as performing firstGeq and then checking against
// point or range version according to cmp, but this version short circuits if
// it can prove that both point and range versions of firstGeq are <=
// readVersion.
bool checkPointRead(Node *n, const std::span<const uint8_t> key,
int64_t readVersion) {
auto remaining = key;
Node *nextSib = nullptr;
for (;;) {
if (std::max(nextSib != nullptr ? nextSib->maxVersion
: std::numeric_limits<int64_t>::lowest(),
n->maxVersion) <= readVersion) {
return true;
}
if (n->partialKeyLen > 0) {
int commonLen = std::min<int>(n->partialKeyLen, remaining.size());
for (int i = 0; i < commonLen; ++i) {
auto c = n->partialKey[i] <=> remaining[i];
if (c == 0) {
continue;
}
if (c > 0) {
goto downLeftSpine;
} else {
n = nextSib;
goto downLeftSpine;
}
}
if (commonLen == n->partialKeyLen) {
// partial key matches
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
} else if (n->partialKeyLen > int(remaining.size())) {
// n is the first physical node greater than remaining, and there's no
// eq node
goto downLeftSpine;
}
}
if (remaining.size() == 0) {
if (n->entryPresent) {
return n->entry.pointVersion <= readVersion;
}
int c = getChildGeq(n, 0);
assert(c >= 0);
n = getChildExists(n, c);
goto downLeftSpine;
} else {
int c = getChildGeq(n, remaining[0]);
int c2 = getChildGeq(n, int(remaining[0]) + 1);
if (c2 >= 0) {
nextSib = getChildExists(n, c2);
}
if (c == remaining[0]) {
n = getChildExists(n, c);
remaining = remaining.subspan(1, remaining.size() - 1);
} else {
if (c >= 0) {
n = getChildExists(n, c);
goto downLeftSpine;
} else {
n = nextSib;
goto downLeftSpine;
}
}
}
}
downLeftSpine:
if (n == nullptr) {
return true;
}
for (;;) {
if (n->maxVersion <= readVersion) {
return true;
}
if (n->entryPresent) {
return n->entry.rangeVersion <= readVersion;
}
int c = getChildGeq(n, 0);
assert(c >= 0);
n = getChildExists(n, c);
}
}
// Returns a pointer to the newly inserted node. caller is reponsible for
// setting 'entry' fields on the result, which may have !entryPresent. The
// search path for `key` will have maxVersion at least `writeVersion` as a
@@ -852,14 +920,12 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
}
}
} else {
auto iter = firstGeq(root, std::span<const uint8_t>(
reads[i].begin.p, reads[i].begin.len));
result[i] = (iter.n == nullptr ? oldestVersion
: iter.cmp == 0
? iter.n->entry.pointVersion
: iter.n->entry.rangeVersion) > reads[i].readVersion
? Conflict
: Commit;
result[i] = checkPointRead(root,
std::span<const uint8_t>(reads[i].begin.p,
reads[i].begin.len),
reads[i].readVersion)
? Commit
: Conflict;
}
}
}