Add gcScanStep

Also remove oldestVersion arg in write call tree
This commit is contained in:
2024-07-02 13:06:53 -07:00
parent cbe40b5dba
commit cdf42fcb34

View File

@@ -2646,9 +2646,9 @@ void destroyTree(Node *root) {
} }
} }
void addPointWrite(Node *&root, InternalVersionT oldestVersion, void addPointWrite(Node *&root, std::span<const uint8_t> key,
std::span<const uint8_t> key, InternalVersionT writeVersion, InternalVersionT writeVersion, NodeAllocators *allocators,
NodeAllocators *allocators, ConflictSet::Impl *impl) { ConflictSet::Impl *impl) {
auto *n = insert<true>(&root, key, writeVersion, allocators, impl); auto *n = insert<true>(&root, key, writeVersion, allocators, impl);
if (!n->entryPresent) { if (!n->entryPresent) {
auto *p = nextLogical(n); auto *p = nextLogical(n);
@@ -2659,24 +2659,22 @@ void addPointWrite(Node *&root, InternalVersionT oldestVersion,
n->entry.pointVersion = writeVersion; n->entry.pointVersion = writeVersion;
setMaxVersion(n, impl, writeVersion); setMaxVersion(n, impl, writeVersion);
n->entry.rangeVersion = n->entry.rangeVersion =
p != nullptr ? p->entry.rangeVersion : oldestVersion; p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
} else { } else {
assert(writeVersion >= n->entry.pointVersion); assert(writeVersion >= n->entry.pointVersion);
n->entry.pointVersion = writeVersion; n->entry.pointVersion = writeVersion;
} }
} }
void addWriteRange(Node *&root, InternalVersionT oldestVersion, void addWriteRange(Node *&root, std::span<const uint8_t> begin,
std::span<const uint8_t> begin, std::span<const uint8_t> end, std::span<const uint8_t> end, InternalVersionT writeVersion,
InternalVersionT writeVersion, NodeAllocators *allocators, NodeAllocators *allocators, ConflictSet::Impl *impl) {
ConflictSet::Impl *impl) {
int lcp = longestCommonPrefix(begin.data(), end.data(), int lcp = longestCommonPrefix(begin.data(), end.data(),
std::min(begin.size(), end.size())); std::min(begin.size(), end.size()));
if (lcp == int(begin.size()) && end.size() == begin.size() + 1 && if (lcp == int(begin.size()) && end.size() == begin.size() + 1 &&
end.back() == 0) { end.back() == 0) {
return addPointWrite(root, oldestVersion, begin, writeVersion, allocators, return addPointWrite(root, begin, writeVersion, allocators, impl);
impl);
} }
const bool beginIsPrefix = lcp == int(begin.size()); const bool beginIsPrefix = lcp == int(begin.size());
auto remaining = begin.subspan(0, lcp); auto remaining = begin.subspan(0, lcp);
@@ -2724,7 +2722,7 @@ void addWriteRange(Node *&root, InternalVersionT oldestVersion,
if (insertedBegin) { if (insertedBegin) {
auto *p = nextLogical(beginNode); auto *p = nextLogical(beginNode);
beginNode->entry.rangeVersion = beginNode->entry.rangeVersion =
p != nullptr ? p->entry.rangeVersion : oldestVersion; p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
beginNode->entry.pointVersion = writeVersion; beginNode->entry.pointVersion = writeVersion;
assert(maxVersion(beginNode, impl) <= writeVersion); assert(maxVersion(beginNode, impl) <= writeVersion);
setMaxVersion(beginNode, impl, writeVersion); setMaxVersion(beginNode, impl, writeVersion);
@@ -2743,7 +2741,7 @@ void addWriteRange(Node *&root, InternalVersionT oldestVersion,
if (insertedEnd) { if (insertedEnd) {
auto *p = nextLogical(endNode); auto *p = nextLogical(endNode);
endNode->entry.pointVersion = endNode->entry.pointVersion =
p != nullptr ? p->entry.rangeVersion : oldestVersion; p != nullptr ? p->entry.rangeVersion : InternalVersionT::zero;
auto m = maxVersion(endNode, impl); auto m = maxVersion(endNode, impl);
setMaxVersion(endNode, impl, setMaxVersion(endNode, impl,
std::max<InternalVersionT>(m, endNode->entry.pointVersion)); std::max<InternalVersionT>(m, endNode->entry.pointVersion));
@@ -2862,30 +2860,18 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
auto end = std::span<const uint8_t>(w.end.p, w.end.len); auto end = std::span<const uint8_t>(w.end.p, w.end.len);
if (w.end.len > 0) { if (w.end.len > 0) {
keyUpdates += 3; keyUpdates += 3;
addWriteRange(root, oldestVersion, begin, end, addWriteRange(root, begin, end, InternalVersionT(writeVersion),
InternalVersionT(writeVersion), &allocators, this); &allocators, this);
} else { } else {
keyUpdates += 2; keyUpdates += 2;
addPointWrite(root, oldestVersion, begin, addPointWrite(root, begin, InternalVersionT(writeVersion), &allocators,
InternalVersionT(writeVersion), &allocators, this); this);
} }
} }
} }
void setOldestVersion(int64_t o) { // Spends up to `fuel` gc'ing, and returns its unused fuel
InternalVersionT oldestVersion{o}; int64_t gcScanStep(int64_t fuel) {
assert(o >= oldestVersionFullPrecision);
this->oldestVersionFullPrecision = o;
this->oldestVersion = oldestVersion;
InternalVersionT::zero = oldestVersion;
#ifdef NDEBUG
// This is here for performance reasons, since we want to amortize the cost
// of storing the search path as a string. In tests, we want to exercise the
// rest of the code often.
if (keyUpdates < 100) {
return;
}
#endif
Node *n = firstGeq(root, removalKey).n; Node *n = firstGeq(root, removalKey).n;
// There's no way to erase removalKey without introducing a key after it // There's no way to erase removalKey without introducing a key after it
assert(n != nullptr); assert(n != nullptr);
@@ -2893,7 +2879,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
if (n == root) { if (n == root) {
n = nextPhysical(n); n = nextPhysical(n);
} }
for (; keyUpdates > 0 && n != nullptr; --keyUpdates) { for (; fuel > 0 && n != nullptr; --fuel) {
if (n->entryPresent && std::max(n->entry.pointVersion, if (n->entryPresent && std::max(n->entry.pointVersion,
n->entry.rangeVersion) <= oldestVersion) { n->entry.rangeVersion) <= oldestVersion) {
// Any transaction n would have prevented from committing is // Any transaction n would have prevented from committing is
@@ -2915,6 +2901,24 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
removalKeyArena = Arena(); removalKeyArena = Arena();
removalKey = getSearchPath(removalKeyArena, n); removalKey = getSearchPath(removalKeyArena, n);
} }
return fuel;
}
void setOldestVersion(int64_t o) {
InternalVersionT oldestVersion{o};
assert(o >= oldestVersionFullPrecision);
this->oldestVersionFullPrecision = o;
this->oldestVersion = oldestVersion;
InternalVersionT::zero = oldestVersion;
#ifdef NDEBUG
// This is here for performance reasons, since we want to amortize the cost
// of storing the search path as a string. In tests, we want to exercise the
// rest of the code often.
if (keyUpdates < 100) {
return;
}
#endif
keyUpdates = gcScanStep(keyUpdates);
} }
explicit Impl(int64_t oldestVersion) explicit Impl(int64_t oldestVersion)