diff --git a/SkipList.cpp b/SkipList.cpp index cff2f09..304717f 100644 --- a/SkipList.cpp +++ b/SkipList.cpp @@ -423,18 +423,23 @@ public: } void swap(SkipList &other) { std::swap(header, other.header); } - void addConflictRanges(const Finger *fingers, int rangeCount, - Version version) { + // Returns the change in the number of entries + int64_t addConflictRanges(const Finger *fingers, int rangeCount, + Version version) { + int64_t result = rangeCount; for (int r = rangeCount - 1; r >= 0; r--) { const Finger &startF = fingers[r * 2]; const Finger &endF = fingers[r * 2 + 1]; - if (endF.found() == nullptr) + if (endF.found() == nullptr) { + ++result; insert(endF, endF.finger[0]->getMaxVersion(0)); + } - remove(startF, endF); + result -= remove(startF, endF); insert(startF, version); } + return result; } void detectConflicts(ReadConflictRange *ranges, int count, @@ -564,9 +569,10 @@ public: } private: - void remove(const Finger &start, const Finger &end) { + // Returns the number of entries removed + int64_t remove(const Finger &start, const Finger &end) { if (start.finger[0] == end.finger[0]) - return; + return 0; Node *x = start.finger[0]->getNext(0); @@ -575,13 +581,16 @@ private: if (start.finger[i] != end.finger[i]) start.finger[i]->setNext(i, end.finger[i]->getNext(i)); + int64_t result = 0; while (true) { Node *next = x->getNext(0); x->destroy(); + ++result; if (x == end.finger[0]) break; x = next; } + return result; } void insert(const Finger &f, Version version) { @@ -772,17 +781,20 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { StringRef values[stripeSize]; int64_t writeVersions[stripeSize / 2]; int ss = stringCount - (stripes - 1) * stripeSize; + int64_t entryDelta = 0; for (int s = stripes - 1; s >= 0; s--) { for (int i = 0; i * 2 < ss; ++i) { const auto &w = combinedWriteConflictRanges[s * stripeSize / 2 + i]; values[i * 2] = w.first; values[i * 2 + 1] = w.second; - keyUpdates += 3; } skipList.find(values, fingers, temp, ss); - skipList.addConflictRanges(fingers, ss / 2, writeVersion); + entryDelta += skipList.addConflictRanges(fingers, ss / 2, writeVersion); ss = stripeSize; } + + // Run gc at least 200% the rate we're inserting entries + keyUpdates += std::max(entryDelta, 0) * 2; } void setOldestVersion(int64_t oldestVersion) { @@ -792,7 +804,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { int temp; std::span key = removalKey; skipList.find(&key, &finger, &temp, 1); - skipList.removeBefore(oldestVersion, finger, std::exchange(keyUpdates, 10)); + skipList.removeBefore(oldestVersion, finger, std::exchange(keyUpdates, 0)); removalArena = Arena(); removalKey = copyToArena( removalArena, {finger.getValue().data(), finger.getValue().size()}); @@ -801,7 +813,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { int64_t totalBytes = 0; private: - int64_t keyUpdates = 10; + int64_t keyUpdates = 0; Arena removalArena; std::span removalKey; int64_t oldestVersion;