6 Commits
Author SHA1 Message Date
andrew 8190d2f24e Update README
Tests / 64 bit versions total: 8220, passed: 8220
Tests / Debug total: 8218, failed: 28, passed: 8190
Tests / SIMD fallback total: 8220, passed: 8220
Tests / Release [clang] total: 8220, passed: 8220
Tests / gcc total: 8220, failed: 28, passed: 8192
Tests / Release [clang,aarch64] total: 5446, passed: 5446
Tests / Coverage total: 5497, failed: 28, passed: 5469
weaselab/conflict-set/pipeline/head There was a failure building this commit
2024-11-20 21:55:37 -08:00
andrew 8251631087 Fix some unintentional generic usages of getChildAndMaxVersion 2024-11-20 21:50:48 -08:00
andrew 90fb2a9542 Remove some usages of generic getFirstChild 2024-11-20 21:43:47 -08:00
andrew 7c01f8ba0f Remove some usages of maxVersion 2024-11-20 21:24:59 -08:00
andrew 0df2db7f8a Remove some bad unlikely annotations found by -Wmisexpect
Using a profile from server_bench
2024-11-20 19:06:50 -08:00
andrew 5e975f3b2b More writes than reads in ServerBench 2024-11-20 17:49:55 -08:00
3 changed files with 78 additions and 89 deletions
+54 -65
View File
@@ -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) {
+22 -22
View File
@@ -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
View File
@@ -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;