From bafe1edfa4e0bfb912880c5d847255866916e56c Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Wed, 31 Jan 2024 14:32:25 -0800 Subject: [PATCH] Remove call to memcmp for partial keys --- ConflictSet.cpp | 53 ++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 1bb5540..114d515 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -37,10 +37,10 @@ struct Node { Node *parent = nullptr; int64_t maxVersion = std::numeric_limits::lowest(); Entry entry; - constexpr static auto kPartialKeyMaxLen = 18; int16_t numChildren = 0; bool entryPresent = false; uint8_t parentsIndex = 0; + constexpr static auto kPartialKeyMaxLen = 10; uint8_t partialKey[kPartialKeyMaxLen]; int8_t partialKeyLen = 0; /* end section that's copied to the next node */ @@ -748,33 +748,40 @@ std::string_view getSearchPath(Arena &arena, Node *n) { Iterator lastLeq(Node *n, const std::span key) { auto remaining = key; for (;;) { - Arena arena; - int commonLen = std::min(n->partialKeyLen, remaining.size()); - if (commonLen > Node::kPartialKeyMaxLen) { - __builtin_unreachable(); + if (n->partialKeyLen > 0) { + int commonLen = std::min(n->partialKeyLen, remaining.size()); + for (int i = 0; i < commonLen; ++i) { + auto c = n->partialKey[i] <=> remaining[i]; + if (c == 0) { + continue; + } + if (c > 0) { + n = prevPhysical(n); + } + goto outerLoop; + } + if (commonLen == n->partialKeyLen) { + // partial key matches + remaining = remaining.subspan(commonLen, remaining.size() - commonLen); + } else if (n->partialKeyLen > int(remaining.size())) { + // n is the first physical node greater than remaining, and there's no + // eq node + n = prevPhysical(n); + goto outerLoop; + } } - int c = memcmp(n->partialKey, remaining.data(), commonLen); - if (c == 0 && commonLen == n->partialKeyLen) { - // partial key matches - remaining = remaining.subspan(commonLen, remaining.size() - commonLen); - } else if (c < 0 || (c == 0 && n->partialKeyLen < int(remaining.size()))) { - // n is the last physical node less than remaining, and there's no eq node - break; - } else if (c > 0 || (c == 0 && n->partialKeyLen > int(remaining.size()))) { - // n is the first physical node greater than remaining, and there's no eq - // node - n = prevPhysical(n); - break; + { + Arena arena; + assert((std::string(getSearchPath(arena, n)) + + std::string((const char *)remaining.data(), remaining.size())) + .ends_with(std::string((const char *)key.data(), key.size()))); } - assert((std::string(getSearchPath(arena, n)) + - std::string((const char *)remaining.data(), remaining.size())) - .ends_with(std::string((const char *)key.data(), key.size()))); if (remaining.size() == 0) { // We've found the physical node corresponding to search path `key` if (n->entryPresent) { return {n, 0}; } else { - break; + goto outerLoop; } } else { int c = getChildLeq(n, remaining[0]); @@ -790,14 +797,14 @@ Iterator lastLeq(Node *n, const std::span key) { if (c >= 0) { n = getChildExists(n, c); } else { - break; + goto outerLoop; } c = getChildLeq(n, 255); } - break; } } } +outerLoop: // Iterate backwards along existing physical nodes until we find a present // entry for (; !n->entryPresent; n = prevPhysical(n)) {