From 69a1b9099d262b3f221f282aeaa71a1f879fa7cd Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Fri, 16 Feb 2024 17:50:21 -0800 Subject: [PATCH] Share common prefix search in addWriteRange --- ConflictSet.cpp | 91 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 25 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index e05d084..8b86573 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -1396,46 +1396,87 @@ void destroyTree(Node *root) { void addWriteRange(Node *&root, int64_t oldestVersion, const ConflictSet::WriteRange &w) { - auto *begin = insert(&root, std::span(w.begin.p, w.begin.len), - w.writeVersion, true); + auto begin = std::span(w.begin.p, w.begin.len); + auto end = std::span(w.end.p, w.end.len); - const bool insertedBegin = !std::exchange(begin->entryPresent, true); + int lcp = longestCommonPrefix(begin.data(), end.data(), + std::min(begin.size(), end.size())); + auto remaining = begin.subspan(0, lcp); + + auto *n = root; + + for (;;) { + if (int(remaining.size()) < n->partialKeyLen + 1) { + break; + } + int i = 0; + for (; i < n->partialKeyLen; ++i) { + if (remaining[i] != n->partialKey[i]) { + break; + } + } + if (i != n->partialKeyLen) { + break; + } + + int c = getChildGeq(n, remaining[n->partialKeyLen]); + if (c != remaining[n->partialKeyLen]) { + break; + } + + n = getChildExists(n, c); + remaining = remaining.subspan(n->partialKeyLen + 1, + remaining.size() - (n->partialKeyLen + 1)); + } + + Node **useAsRoot = n->parent == nullptr + ? &root + : &getChildExists(n->parent, n->parentsIndex); + + int consumed = lcp - remaining.size(); + + consumed = 0; + useAsRoot = &root; + + begin = begin.subspan(consumed, begin.size() - consumed); + end = end.subspan(consumed, end.size() - consumed); + + auto *beginNode = insert(useAsRoot, begin, w.writeVersion, true); + + const bool insertedBegin = !std::exchange(beginNode->entryPresent, true); if (insertedBegin) { - auto *p = nextLogical(begin); - begin->entry.rangeVersion = + auto *p = nextLogical(beginNode); + beginNode->entry.rangeVersion = p != nullptr ? p->entry.rangeVersion : oldestVersion; - begin->entry.pointVersion = w.writeVersion; - begin->maxVersion = w.writeVersion; + beginNode->entry.pointVersion = w.writeVersion; + beginNode->maxVersion = w.writeVersion; } - begin->maxVersion = std::max(begin->maxVersion, w.writeVersion); - begin->entry.pointVersion = - std::max(begin->entry.pointVersion, w.writeVersion); + beginNode->maxVersion = std::max(beginNode->maxVersion, w.writeVersion); + beginNode->entry.pointVersion = + std::max(beginNode->entry.pointVersion, w.writeVersion); - auto *end = insert(&root, std::span(w.end.p, w.end.len), - w.writeVersion, false); + auto *endNode = insert(useAsRoot, end, w.writeVersion, false); - const bool insertedEnd = !std::exchange(end->entryPresent, true); + const bool insertedEnd = !std::exchange(endNode->entryPresent, true); if (insertedEnd) { - auto *p = nextLogical(end); - end->entry.pointVersion = + auto *p = nextLogical(endNode); + endNode->entry.pointVersion = p != nullptr ? p->entry.rangeVersion : oldestVersion; - end->maxVersion = std::max(end->maxVersion, end->entry.pointVersion); + endNode->maxVersion = + std::max(endNode->maxVersion, endNode->entry.pointVersion); } - end->entry.rangeVersion = w.writeVersion; + endNode->entry.rangeVersion = w.writeVersion; if (insertedEnd) { - // begin may have been invalidated - auto iter = - firstGeq(root, std::span(w.begin.p, w.begin.len)); - assert(iter.cmp == 0); - begin = iter.n; + // beginNode may have been invalidated + beginNode = insert(useAsRoot, begin, w.writeVersion, true); } - for (begin = nextLogical(begin); begin != end;) { - auto *old = begin; - begin = nextLogical(begin); + for (beginNode = nextLogical(beginNode); beginNode != endNode;) { + auto *old = beginNode; + beginNode = nextLogical(beginNode); old->entryPresent = false; if (old->numChildren == 0 && old->parent != nullptr) { eraseChild(old->parent, old->parentsIndex);