Compare commits
6
Commits
bcbae026b2
...
8190d2f24e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8190d2f24e | ||
|
|
8251631087 | ||
|
|
90fb2a9542 | ||
|
|
7c01f8ba0f | ||
|
|
0df2db7f8a | ||
|
|
5e975f3b2b |
+54
-65
@@ -1379,6 +1379,12 @@ TaggedNodePointer getFirstChild(Node *self) {
|
|||||||
// GCOVR_EXCL_STOP
|
// GCOVR_EXCL_STOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkRangeVersionOfFirstGeq(Node *node, InternalVersionT readVersion) {
|
||||||
|
for (; !node->entryPresent; node = getFirstChild(node)) {
|
||||||
|
}
|
||||||
|
return node->entry.rangeVersion <= readVersion;
|
||||||
|
}
|
||||||
|
|
||||||
// self must not be the root
|
// self must not be the root
|
||||||
void maybeDecreaseCapacity(Node *&self, WriteContext *writeContext,
|
void maybeDecreaseCapacity(Node *&self, WriteContext *writeContext,
|
||||||
ConflictSet::Impl *impl);
|
ConflictSet::Impl *impl);
|
||||||
@@ -2670,18 +2676,19 @@ bool checkRangeStartsWith(NodeT *nTyped, TrivialSpan key, int begin, int end,
|
|||||||
readContext);
|
readContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *child = getChild(nTyped, remaining[0]);
|
auto cAndV = getChildAndMaxVersion(nTyped, remaining[0]);
|
||||||
|
Node *child = cAndV.child;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(nTyped, remaining[0]);
|
auto c = getChildGeq(nTyped, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
n = c;
|
n = c;
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(nTyped);
|
n = nextSibling(nTyped);
|
||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2695,13 +2702,13 @@ bool checkRangeStartsWith(NodeT *nTyped, TrivialSpan key, int begin, int end,
|
|||||||
if (i < commonLen) {
|
if (i < commonLen) {
|
||||||
auto c = n->partialKey()[i] <=> remaining[i];
|
auto c = n->partialKey()[i] <=> remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = nextSibling(n);
|
||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(n->partialKeyLen > remaining.size());
|
assert(n->partialKeyLen > remaining.size());
|
||||||
@@ -2710,17 +2717,12 @@ bool checkRangeStartsWith(NodeT *nTyped, TrivialSpan key, int begin, int end,
|
|||||||
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return maxVersion(n) <= readVersion;
|
return cAndV.maxVersion <= readVersion;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
|
|
||||||
downLeftSpine:
|
|
||||||
for (; !n->entryPresent; n = getFirstChild(n)) {
|
|
||||||
}
|
|
||||||
return n->entry.rangeVersion <= readVersion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
@@ -3228,7 +3230,7 @@ template <class NodeT> void iter(Job *job, Context *context) {
|
|||||||
if (n->partialKeyLen > 0) {
|
if (n->partialKeyLen > 0) {
|
||||||
int commonLen = std::min<int>(n->partialKeyLen, job->begin.size());
|
int commonLen = std::min<int>(n->partialKeyLen, job->begin.size());
|
||||||
int i = longestCommonPrefix(n->partialKey(), job->begin.data(), commonLen);
|
int i = longestCommonPrefix(n->partialKey(), job->begin.data(), commonLen);
|
||||||
if (i < commonLen) [[unlikely]] {
|
if (i < commonLen) {
|
||||||
auto c = n->partialKey()[i] <=> job->begin[i];
|
auto c = n->partialKey()[i] <=> job->begin[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
||||||
@@ -3261,7 +3263,7 @@ template <class NodeT> void iter(Job *job, Context *context) {
|
|||||||
|
|
||||||
++context->readContext.point_read_iterations_accum;
|
++context->readContext.point_read_iterations_accum;
|
||||||
|
|
||||||
if (job->begin.size() == 0) [[unlikely]] {
|
if (job->begin.size() == 0) {
|
||||||
if (n->entryPresent) {
|
if (n->entryPresent) {
|
||||||
job->setResult(n->entry.pointVersion <= job->readVersion);
|
job->setResult(n->entry.pointVersion <= job->readVersion);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
@@ -3275,7 +3277,7 @@ template <class NodeT> void iter(Job *job, Context *context) {
|
|||||||
auto [taggedChild, maxV] = getChildAndMaxVersion(n, job->begin[0]);
|
auto [taggedChild, maxV] = getChildAndMaxVersion(n, job->begin[0]);
|
||||||
job->maxV = maxV;
|
job->maxV = maxV;
|
||||||
Node *child = taggedChild;
|
Node *child = taggedChild;
|
||||||
if (child == nullptr) [[unlikely]] {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, job->begin[0]);
|
auto c = getChildGeq(n, job->begin[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
@@ -3567,8 +3569,8 @@ PRESERVE_NONE void done_common_prefix_iter(Job *job, Context *context) {
|
|||||||
// This is a hack
|
// This is a hack
|
||||||
--job->lcp;
|
--job->lcp;
|
||||||
|
|
||||||
auto c = getChild(n, job->remaining[0]);
|
auto cAndV = getChildAndMaxVersion(n, job->remaining[0]);
|
||||||
Node *child = c;
|
Node *child = cAndV.child;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, job->remaining[0]);
|
auto c = getChildGeq(n, job->remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -3587,7 +3589,8 @@ PRESERVE_NONE void done_common_prefix_iter(Job *job, Context *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
job->n = child;
|
job->n = child;
|
||||||
job->continuation = rightSideIterTable[c.getType()];
|
job->maxV = cAndV.maxVersion;
|
||||||
|
job->continuation = rightSideIterTable[cAndV.child.getType()];
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3703,7 +3706,7 @@ PRESERVE_NONE void left_side_iter(Job *job, Context *context) {
|
|||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [c, maxV] = getChildAndMaxVersion(job->n, job->remaining[0]);
|
auto [c, maxV] = getChildAndMaxVersion(n, job->remaining[0]);
|
||||||
job->maxV = maxV;
|
job->maxV = maxV;
|
||||||
Node *child = c;
|
Node *child = c;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
@@ -3732,8 +3735,8 @@ PRESERVE_NONE void done_left_side_iter(Job *job, Context *context) {
|
|||||||
job->n = job->commonPrefixNode;
|
job->n = job->commonPrefixNode;
|
||||||
job->remaining = job->end;
|
job->remaining = job->end;
|
||||||
|
|
||||||
auto c = getChild(job->n, job->remaining[0]);
|
auto cAndV = getChildAndMaxVersion(job->n, job->remaining[0]);
|
||||||
Node *child = c;
|
Node *child = cAndV.child;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(job->n, job->remaining[0]);
|
auto c = getChildGeq(job->n, job->remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -3753,7 +3756,8 @@ PRESERVE_NONE void done_left_side_iter(Job *job, Context *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
job->n = child;
|
job->n = child;
|
||||||
job->continuation = rightSideIterTable[c.getType()];
|
job->maxV = cAndV.maxVersion;
|
||||||
|
job->continuation = rightSideIterTable[cAndV.child.getType()];
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3799,7 +3803,7 @@ PRESERVE_NONE void right_side_iter(Job *job, Context *context) {
|
|||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
if ((n->parent != job->commonPrefixNode || i >= job->lcp) &&
|
if ((n->parent != job->commonPrefixNode || i >= job->lcp) &&
|
||||||
maxVersion(n) > job->readVersion) {
|
job->maxV > job->readVersion) {
|
||||||
job->setResult(false);
|
job->setResult(false);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
@@ -3844,8 +3848,8 @@ PRESERVE_NONE void right_side_iter(Job *job, Context *context) {
|
|||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto c = getChild(job->n, job->remaining[0]);
|
auto cAndV = getChildAndMaxVersion(n, job->remaining[0]);
|
||||||
Node *child = c;
|
Node *child = cAndV.child;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, job->remaining[0]);
|
auto c = getChildGeq(n, job->remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -3865,7 +3869,8 @@ PRESERVE_NONE void right_side_iter(Job *job, Context *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
job->n = child;
|
job->n = child;
|
||||||
job->continuation = rightSideIterTable[c.getType()];
|
job->maxV = cAndV.maxVersion;
|
||||||
|
job->continuation = rightSideIterTable[cAndV.child.getType()];
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4074,7 +4079,7 @@ void pointIter(Job *job, Context *context) {
|
|||||||
n->childMaxVersion[job->childIndex] = context->writeVersion;
|
n->childMaxVersion[job->childIndex] = context->writeVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (job->remaining.size() == 0) [[unlikely]] {
|
if (job->remaining.size() == 0) {
|
||||||
*job->result = {job->n, job->remaining};
|
*job->result = {job->n, job->remaining};
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
@@ -4430,7 +4435,7 @@ bool checkPointRead(Node *n, const TrivialSpan key,
|
|||||||
return n->entry.pointVersion <= readVersion;
|
return n->entry.pointVersion <= readVersion;
|
||||||
}
|
}
|
||||||
n = getFirstChild(n);
|
n = getFirstChild(n);
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [c, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
auto [c, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
||||||
@@ -4439,13 +4444,13 @@ bool checkPointRead(Node *n, const TrivialSpan key,
|
|||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
n = c;
|
n = c;
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = nextSibling(n);
|
||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4458,13 +4463,13 @@ bool checkPointRead(Node *n, const TrivialSpan key,
|
|||||||
if (i < commonLen) {
|
if (i < commonLen) {
|
||||||
auto c = n->partialKey()[i] <=> remaining[i];
|
auto c = n->partialKey()[i] <=> remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = nextSibling(n);
|
||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commonLen == n->partialKeyLen) {
|
if (commonLen == n->partialKeyLen) {
|
||||||
@@ -4473,7 +4478,7 @@ bool checkPointRead(Node *n, const TrivialSpan key,
|
|||||||
} else if (n->partialKeyLen > remaining.size()) {
|
} else if (n->partialKeyLen > remaining.size()) {
|
||||||
// n is the first physical node greater than remaining, and there's no
|
// n is the first physical node greater than remaining, and there's no
|
||||||
// eq node
|
// eq node
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4482,10 +4487,6 @@ bool checkPointRead(Node *n, const TrivialSpan key,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
downLeftSpine:
|
|
||||||
for (; !n->entryPresent; n = getFirstChild(n)) {
|
|
||||||
}
|
|
||||||
return n->entry.rangeVersion <= readVersion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logically this is the same as performing firstGeq and then checking against
|
// Logically this is the same as performing firstGeq and then checking against
|
||||||
@@ -4510,13 +4511,13 @@ bool checkPrefixRead(Node *n, const TrivialSpan key,
|
|||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
n = c;
|
n = c;
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = nextSibling(n);
|
||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4529,13 +4530,13 @@ bool checkPrefixRead(Node *n, const TrivialSpan key,
|
|||||||
if (i < commonLen) {
|
if (i < commonLen) {
|
||||||
auto c = n->partialKey()[i] <=> remaining[i];
|
auto c = n->partialKey()[i] <=> remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = nextSibling(n);
|
||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commonLen == n->partialKeyLen) {
|
if (commonLen == n->partialKeyLen) {
|
||||||
@@ -4545,10 +4546,10 @@ bool checkPrefixRead(Node *n, const TrivialSpan key,
|
|||||||
// n is the first physical node greater than remaining, and there's no
|
// n is the first physical node greater than remaining, and there's no
|
||||||
// eq node. All physical nodes that start with prefix are reachable from
|
// eq node. All physical nodes that start with prefix are reachable from
|
||||||
// n.
|
// n.
|
||||||
if (maxVersion(n) > readVersion) {
|
if (maxV > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4557,10 +4558,6 @@ bool checkPrefixRead(Node *n, const TrivialSpan key,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
downLeftSpine:
|
|
||||||
for (; !n->entryPresent; n = getFirstChild(n)) {
|
|
||||||
}
|
|
||||||
return n->entry.rangeVersion <= readVersion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if the max version among all keys that start with key[:prefixLen]
|
// Return true if the max version among all keys that start with key[:prefixLen]
|
||||||
@@ -4590,7 +4587,7 @@ bool checkRangeLeftSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
if (searchPathLen < prefixLen) {
|
if (searchPathLen < prefixLen) {
|
||||||
n = c;
|
n = c;
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
n = c;
|
n = c;
|
||||||
return maxVersion(n) <= readVersion;
|
return maxVersion(n) <= readVersion;
|
||||||
@@ -4599,7 +4596,7 @@ bool checkRangeLeftSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4615,18 +4612,18 @@ bool checkRangeLeftSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
auto c = n->partialKey()[i] <=> remaining[i];
|
auto c = n->partialKey()[i] <=> remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
if (searchPathLen < prefixLen) {
|
if (searchPathLen < prefixLen) {
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return maxVersion(n) <= readVersion;
|
return maxV <= readVersion;
|
||||||
} else {
|
} else {
|
||||||
n = nextSibling(n);
|
n = nextSibling(n);
|
||||||
if (n == nullptr) {
|
if (n == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commonLen == n->partialKeyLen) {
|
if (commonLen == n->partialKeyLen) {
|
||||||
@@ -4637,17 +4634,13 @@ bool checkRangeLeftSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
if (n->entryPresent && n->entry.rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return maxVersion(n) <= readVersion;
|
return maxV <= readVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maxV <= readVersion) {
|
if (maxV <= readVersion) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
downLeftSpine:
|
|
||||||
for (; !n->entryPresent; n = getFirstChild(n)) {
|
|
||||||
}
|
|
||||||
return n->entry.rangeVersion <= readVersion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if the max version among all keys that start with key[:prefixLen]
|
// Return true if the max version among all keys that start with key[:prefixLen]
|
||||||
@@ -4661,7 +4654,7 @@ bool checkRangeRightSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
for (;; ++readContext->range_read_iterations_accum) {
|
for (;; ++readContext->range_read_iterations_accum) {
|
||||||
assert(searchPathLen <= key.size());
|
assert(searchPathLen <= key.size());
|
||||||
if (remaining.size() == 0) {
|
if (remaining.size() == 0) {
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchPathLen >= prefixLen) {
|
if (searchPathLen >= prefixLen) {
|
||||||
@@ -4685,7 +4678,7 @@ bool checkRangeRightSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
n = c;
|
n = c;
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
} else {
|
} else {
|
||||||
goto backtrack;
|
goto backtrack;
|
||||||
}
|
}
|
||||||
@@ -4703,7 +4696,7 @@ bool checkRangeRightSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
++searchPathLen;
|
++searchPathLen;
|
||||||
auto c = n->partialKey()[i] <=> remaining[i];
|
auto c = n->partialKey()[i] <=> remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
} else {
|
} else {
|
||||||
if (searchPathLen > prefixLen && n->entryPresent &&
|
if (searchPathLen > prefixLen && n->entryPresent &&
|
||||||
n->entry.rangeVersion > readVersion) {
|
n->entry.rangeVersion > readVersion) {
|
||||||
@@ -4716,7 +4709,7 @@ bool checkRangeRightSide(Node *n, TrivialSpan key, int prefixLen,
|
|||||||
// partial key matches
|
// partial key matches
|
||||||
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
|
remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
|
||||||
} else if (n->partialKeyLen > remaining.size()) {
|
} else if (n->partialKeyLen > remaining.size()) {
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4735,13 +4728,9 @@ backtrack:
|
|||||||
n = n->parent;
|
n = n->parent;
|
||||||
} else {
|
} else {
|
||||||
n = next;
|
n = next;
|
||||||
goto downLeftSpine;
|
return checkRangeVersionOfFirstGeq(n, readVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
downLeftSpine:
|
|
||||||
for (; !n->entryPresent; n = getFirstChild(n)) {
|
|
||||||
}
|
|
||||||
return n->entry.rangeVersion <= readVersion;
|
|
||||||
}
|
}
|
||||||
bool checkRangeRead(Node *n, TrivialSpan begin, TrivialSpan end,
|
bool checkRangeRead(Node *n, TrivialSpan begin, TrivialSpan end,
|
||||||
InternalVersionT readVersion, ReadContext *readContext) {
|
InternalVersionT readVersion, ReadContext *readContext) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Hardware for all benchmarks is an AMD Ryzen 9 7900 with (2x32GB) 5600MT/s CL28-3
|
|||||||
```
|
```
|
||||||
$ clang++ --version
|
$ clang++ --version
|
||||||
|
|
||||||
Ubuntu clang version 20.0.0 (++20241119082716+7e85cb8a8a9d-1~exp1~20241119082825.551)
|
Ubuntu clang version 20.0.0 (++20241120082228+86734c857724-1~exp1~20241120202359.554)
|
||||||
Target: x86_64-pc-linux-gnu
|
Target: x86_64-pc-linux-gnu
|
||||||
Thread model: posix
|
Thread model: posix
|
||||||
InstalledDir: /usr/lib/llvm-20/bin
|
InstalledDir: /usr/lib/llvm-20/bin
|
||||||
@@ -19,30 +19,30 @@ InstalledDir: /usr/lib/llvm-20/bin
|
|||||||
|
|
||||||
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|
||||||
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|
||||||
| 175.88 | 5,685,575.81 | 0.0% | 3,014.03 | 883.13 | 3.413 | 504.59 | 0.0% | 2.10 | `point reads`
|
| 161.29 | 6,200,056.17 | 0.1% | 3,014.03 | 831.04 | 3.627 | 504.59 | 0.0% | 1.93 | `point reads`
|
||||||
| 173.35 | 5,768,718.52 | 0.0% | 2,954.16 | 869.59 | 3.397 | 490.17 | 0.0% | 2.07 | `prefix reads`
|
| 158.32 | 6,316,160.64 | 0.1% | 2,954.16 | 815.80 | 3.621 | 490.17 | 0.0% | 1.89 | `prefix reads`
|
||||||
| 251.74 | 3,972,274.68 | 0.1% | 3,592.41 | 1,265.71 | 2.838 | 629.31 | 0.0% | 3.01 | `range reads`
|
| 237.39 | 4,212,409.50 | 0.2% | 3,592.41 | 1,233.96 | 2.911 | 629.31 | 0.0% | 2.84 | `range reads`
|
||||||
| 472.13 | 2,118,079.83 | 0.2% | 4,450.57 | 2,377.84 | 1.872 | 707.92 | 2.3% | 5.60 | `point writes`
|
| 442.11 | 2,261,878.94 | 0.0% | 4,450.57 | 2,314.25 | 1.923 | 707.92 | 2.1% | 5.28 | `point writes`
|
||||||
| 471.34 | 2,121,609.91 | 0.0% | 4,410.22 | 2,372.55 | 1.859 | 694.74 | 2.3% | 5.61 | `prefix writes`
|
| 439.89 | 2,273,308.53 | 0.1% | 4,410.22 | 2,302.29 | 1.916 | 694.74 | 2.1% | 5.25 | `prefix writes`
|
||||||
| 306.69 | 3,260,650.68 | 0.0% | 2,315.38 | 1,550.33 | 1.493 | 396.69 | 3.3% | 3.68 | `range writes`
|
| 290.96 | 3,436,936.78 | 0.0% | 2,315.38 | 1,528.68 | 1.515 | 396.69 | 3.3% | 3.49 | `range writes`
|
||||||
| 502.70 | 1,989,277.15 | 0.9% | 6,999.33 | 2,527.47 | 2.769 | 1,251.74 | 1.3% | 0.06 | `monotonic increasing point writes`
|
| 476.93 | 2,096,762.02 | 0.6% | 6,999.33 | 2,484.94 | 2.817 | 1,251.73 | 1.3% | 0.06 | `monotonic increasing point writes`
|
||||||
| 138,097.67 | 7,241.25 | 0.7% | 807,445.67 | 699,899.00 | 1.154 | 144,584.50 | 0.8% | 0.01 | `worst case for radix tree`
|
| 131,736.57 | 7,590.91 | 1.1% | 807,444.50 | 704,941.71 | 1.145 | 144,584.60 | 0.9% | 0.01 | `worst case for radix tree`
|
||||||
| 46.29 | 21,605,126.00 | 1.0% | 902.00 | 230.73 | 3.909 | 132.00 | 0.0% | 0.01 | `create and destroy`
|
| 45.50 | 21,978,369.95 | 1.1% | 902.00 | 232.36 | 3.882 | 132.00 | 0.0% | 0.01 | `create and destroy`
|
||||||
|
|
||||||
## Radix tree (this implementation)
|
## Radix tree (this implementation)
|
||||||
|
|
||||||
|
|
||||||
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|
||||||
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|
||||||
| 14.04 | 71,216,855.01 | 0.1% | 245.98 | 70.38 | 3.495 | 31.49 | 0.6% | 0.17 | `point reads`
|
| 12.36 | 80,885,626.43 | 0.2% | 243.56 | 63.62 | 3.828 | 31.07 | 0.6% | 0.15 | `point reads`
|
||||||
| 14.57 | 68,630,592.89 | 0.1% | 297.83 | 72.93 | 4.084 | 40.34 | 0.5% | 0.17 | `prefix reads`
|
| 14.18 | 70,502,196.81 | 0.1% | 297.72 | 73.13 | 4.071 | 40.31 | 0.5% | 0.17 | `prefix reads`
|
||||||
| 35.28 | 28,347,588.39 | 0.2% | 783.70 | 176.57 | 4.438 | 107.65 | 0.2% | 0.42 | `range reads`
|
| 33.44 | 29,901,623.04 | 0.1% | 767.90 | 172.42 | 4.454 | 101.32 | 0.2% | 0.40 | `range reads`
|
||||||
| 20.64 | 48,453,280.08 | 0.0% | 378.97 | 103.31 | 3.668 | 49.92 | 0.7% | 0.25 | `point writes`
|
| 19.48 | 51,342,564.70 | 0.3% | 374.45 | 100.43 | 3.728 | 48.92 | 0.5% | 0.23 | `point writes`
|
||||||
| 39.14 | 25,551,096.17 | 0.0% | 672.00 | 196.08 | 3.427 | 101.28 | 0.3% | 0.47 | `prefix writes`
|
| 37.46 | 26,694,471.44 | 0.1% | 672.00 | 193.14 | 3.479 | 101.28 | 0.3% | 0.45 | `prefix writes`
|
||||||
| 39.88 | 25,075,121.85 | 0.0% | 738.26 | 199.71 | 3.697 | 111.59 | 0.1% | 0.49 | `range writes`
|
| 38.78 | 25,784,784.34 | 0.0% | 738.26 | 199.93 | 3.693 | 111.59 | 0.1% | 0.47 | `range writes`
|
||||||
| 79.36 | 12,601,312.65 | 0.5% | 1,447.65 | 398.77 | 3.630 | 275.61 | 0.1% | 0.01 | `monotonic increasing point writes`
|
| 76.05 | 13,148,995.74 | 0.7% | 1,450.77 | 397.16 | 3.653 | 275.72 | 0.0% | 0.01 | `monotonic increasing point writes`
|
||||||
| 307,037.33 | 3,256.93 | 0.3% | 4,043,060.50 | 1,549,199.33 | 2.610 | 714,828.00 | 0.1% | 0.01 | `worst case for radix tree`
|
| 286,920.33 | 3,485.29 | 0.4% | 4,117,948.00 | 1,521,352.00 | 2.707 | 714,833.00 | 0.1% | 0.01 | `worst case for radix tree`
|
||||||
| 97.00 | 10,309,246.47 | 0.2% | 1,986.00 | 487.06 | 4.078 | 315.00 | 0.0% | 0.01 | `create and destroy`
|
| 95.66 | 10,453,798.72 | 0.5% | 1,986.00 | 495.04 | 4.012 | 315.00 | 0.0% | 0.01 | `create and destroy`
|
||||||
|
|
||||||
# "Real data" test
|
# "Real data" test
|
||||||
|
|
||||||
@@ -51,13 +51,13 @@ Point queries only. Gc ratio is the ratio of time spent doing garbage collection
|
|||||||
## skip list
|
## skip list
|
||||||
|
|
||||||
```
|
```
|
||||||
Check: 4.66163 seconds, 361.716 MB/s, Add: 3.97534 seconds, 144.726 MB/s, Gc ratio: 33.3998%, Peak idle memory: 5.61007e+06
|
Check: 4.53508 seconds, 371.81 MB/s, Add: 3.81222 seconds, 150.919 MB/s, Gc ratio: 33.66%, Peak idle memory: 5.61007e+06
|
||||||
```
|
```
|
||||||
|
|
||||||
## radix tree
|
## radix tree
|
||||||
|
|
||||||
```
|
```
|
||||||
Check: 1.01776 seconds, 1656.77 MB/s, Add: 1.2718 seconds, 452.38 MB/s, Gc ratio: 38.626%, Peak idle memory: 2.05667e+06
|
Check: 0.957735 seconds, 1760.6 MB/s, Add: 1.19942 seconds, 479.678 MB/s, Gc ratio: 38.6069%, Peak idle memory: 2.05667e+06
|
||||||
```
|
```
|
||||||
|
|
||||||
## hash table
|
## hash table
|
||||||
@@ -65,6 +65,6 @@ Check: 1.01776 seconds, 1656.77 MB/s, Add: 1.2718 seconds, 452.38 MB/s, Gc ratio
|
|||||||
(The hash table implementation doesn't work on range queries, and its purpose is to provide an idea of how fast point queries can be)
|
(The hash table implementation doesn't work on range queries, and its purpose is to provide an idea of how fast point queries can be)
|
||||||
|
|
||||||
```
|
```
|
||||||
Check: 0.859188 seconds, 1962.54 MB/s, Add: 0.714174 seconds, 805.596 MB/s, Gc ratio: 34.9552%, Peak idle memory: 0
|
Check: 0.804598 seconds, 2095.69 MB/s, Add: 0.671221 seconds, 857.147 MB/s, Gc ratio: 35.0034%, Peak idle memory: 0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -161,8 +161,8 @@ template <class... Ts> std::string tupleKey(const Ts &...ts) {
|
|||||||
|
|
||||||
constexpr int kTotalKeyRange = 1'000'000'000;
|
constexpr int kTotalKeyRange = 1'000'000'000;
|
||||||
constexpr int kWindowSize = 1'000'000;
|
constexpr int kWindowSize = 1'000'000;
|
||||||
constexpr int kNumReadKeysPerTx = 10;
|
constexpr int kNumReadKeysPerTx = 5;
|
||||||
constexpr int kNumWriteKeysPerTx = 5;
|
constexpr int kNumWriteKeysPerTx = 10;
|
||||||
|
|
||||||
struct Transaction {
|
struct Transaction {
|
||||||
std::vector<std::string> keys;
|
std::vector<std::string> keys;
|
||||||
|
|||||||
Reference in New Issue
Block a user