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