Improve worst-case radix tree checkRangeRead
This commit is contained in:
@@ -1621,28 +1621,31 @@ downLeftSpine:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the max version among all keys starting with the search path of n +
|
// Return whether or not the max version among all keys starting with the search
|
||||||
// [child], where child in (begin, end). Does not account for the range version
|
// path of n + [child], where child in (begin, end) is <= readVersion. Does not
|
||||||
// of firstGt(searchpath(n) + [end - 1])
|
// account for the range version of firstGt(searchpath(n) + [end - 1])
|
||||||
int64_t maxBetweenExclusive(Node *n, int begin, int end) {
|
bool checkMaxBetweenExclusive(Node *n, int begin, int end,
|
||||||
|
int64_t readVersion) {
|
||||||
assume(-1 <= begin);
|
assume(-1 <= begin);
|
||||||
assume(begin <= 256);
|
assume(begin <= 256);
|
||||||
assume(-1 <= end);
|
assume(-1 <= end);
|
||||||
assume(end <= 256);
|
assume(end <= 256);
|
||||||
assume(begin < end);
|
assume(begin < end);
|
||||||
int64_t result = std::numeric_limits<int64_t>::lowest();
|
|
||||||
{
|
{
|
||||||
int c = getChildGeq(n, begin + 1);
|
int c = getChildGeq(n, begin + 1);
|
||||||
if (c >= 0 && c < end) {
|
if (c >= 0 && c < end) {
|
||||||
auto *child = getChildExists(n, c);
|
auto *child = getChildExists(n, c);
|
||||||
if (child->entryPresent) {
|
if (child->entryPresent) {
|
||||||
result = std::max(result, child->entry.rangeVersion);
|
if (!(child->entry.rangeVersion <= readVersion)) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
begin = c;
|
begin = c;
|
||||||
} else {
|
} else {
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (n->getType()) {
|
switch (n->getType()) {
|
||||||
case Type_Node0: // GCOVR_EXCL_LINE
|
case Type_Node0: // GCOVR_EXCL_LINE
|
||||||
// We would have returned above, after not finding a child
|
// We would have returned above, after not finding a child
|
||||||
@@ -1651,7 +1654,9 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) {
|
|||||||
auto *self = static_cast<Node3 *>(n);
|
auto *self = static_cast<Node3 *>(n);
|
||||||
for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) {
|
for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) {
|
||||||
if (begin <= self->index[i]) {
|
if (begin <= self->index[i]) {
|
||||||
result = std::max(result, self->children[i].childMaxVersion);
|
if (self->children[i].childMaxVersion > readVersion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -1659,37 +1664,45 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) {
|
|||||||
auto *self = static_cast<Node16 *>(n);
|
auto *self = static_cast<Node16 *>(n);
|
||||||
for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) {
|
for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) {
|
||||||
if (begin <= self->index[i]) {
|
if (begin <= self->index[i]) {
|
||||||
result = std::max(result, self->children[i].childMaxVersion);
|
if (self->children[i].childMaxVersion > readVersion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Type_Node48: {
|
case Type_Node48: {
|
||||||
|
bool conflict[256] = {};
|
||||||
auto *self = static_cast<Node48 *>(n);
|
auto *self = static_cast<Node48 *>(n);
|
||||||
self->bitSet.forEachInRange(
|
self->bitSet.forEachInRange(
|
||||||
[&](int i) {
|
[&](int i) {
|
||||||
result =
|
conflict[i] =
|
||||||
std::max(result, self->children[self->index[i]].childMaxVersion);
|
self->children[self->index[i]].childMaxVersion > readVersion;
|
||||||
},
|
},
|
||||||
begin, end);
|
begin, end);
|
||||||
break;
|
bool result = true;
|
||||||
|
for (auto c : conflict) {
|
||||||
|
result &= !c;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
case Type_Node256: {
|
case Type_Node256: {
|
||||||
|
bool conflict[256] = {};
|
||||||
auto *self = static_cast<Node256 *>(n);
|
auto *self = static_cast<Node256 *>(n);
|
||||||
self->bitSet.forEachInRange(
|
self->bitSet.forEachInRange(
|
||||||
[&](int i) {
|
[&](int i) {
|
||||||
result = std::max(result, self->children[i].childMaxVersion);
|
conflict[i] = self->children[i].childMaxVersion > readVersion;
|
||||||
},
|
},
|
||||||
begin, end);
|
begin, end);
|
||||||
break;
|
bool result = true;
|
||||||
|
for (auto c : conflict) {
|
||||||
|
result &= !c;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
default: // GCOVR_EXCL_LINE
|
default: // GCOVR_EXCL_LINE
|
||||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
}
|
}
|
||||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
return true;
|
||||||
fprintf(stderr, "At `%s', max version in (%02x, %02x) is %" PRId64 "\n",
|
|
||||||
getSearchPathPrintable(n).c_str(), begin, end, result);
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<uint8_t> getSearchPath(Arena &arena, Node *n) {
|
Vector<uint8_t> getSearchPath(Arena &arena, Node *n) {
|
||||||
@@ -1722,7 +1735,7 @@ bool checkRangeStartsWith(Node *n, std::span<const uint8_t> key, int begin,
|
|||||||
#endif
|
#endif
|
||||||
auto remaining = key;
|
auto remaining = key;
|
||||||
if (remaining.size() == 0) {
|
if (remaining.size() == 0) {
|
||||||
return maxBetweenExclusive(n, begin, end) <= readVersion;
|
return checkMaxBetweenExclusive(n, begin, end, readVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *child = getChild(n, remaining[0]);
|
auto *child = getChild(n, remaining[0]);
|
||||||
@@ -1821,7 +1834,7 @@ struct CheckRangeLeftSide {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (searchPathLen >= prefixLen) {
|
if (searchPathLen >= prefixLen) {
|
||||||
if (maxBetweenExclusive(n, remaining[0], 256) > readVersion) {
|
if (!checkMaxBetweenExclusive(n, remaining[0], 256, readVersion)) {
|
||||||
ok = false;
|
ok = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1963,7 +1976,7 @@ struct CheckRangeRightSide {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxBetweenExclusive(n, -1, remaining[0]) > readVersion) {
|
if (!checkMaxBetweenExclusive(n, -1, remaining[0], readVersion)) {
|
||||||
ok = false;
|
ok = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
___stack_chk_fail
|
||||||
|
___stack_chk_guard
|
||||||
__tlv_bootstrap
|
__tlv_bootstrap
|
||||||
_abort
|
_abort
|
||||||
_bzero
|
_bzero
|
||||||
|
Reference in New Issue
Block a user