Improve range write performance
This commit is contained in:
@@ -8,3 +8,11 @@ repos:
|
|||||||
rev: e2c2116d86a80e72e7146a06e68b7c228afc6319
|
rev: e2c2116d86a80e72e7146a06e68b7c228afc6319
|
||||||
hooks:
|
hooks:
|
||||||
- id: cmake-format
|
- id: cmake-format
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: debug verbose check
|
||||||
|
name: disallow checking in DEBUG_VERBOSE=1
|
||||||
|
description: disallow checking in DEBUG_VERBOSE=1
|
||||||
|
entry: '^#define DEBUG_VERBOSE 1$'
|
||||||
|
language: pygrep
|
||||||
|
types: [c++]
|
100
ConflictSet.cpp
100
ConflictSet.cpp
@@ -543,6 +543,27 @@ Node *&getOrCreateChild(Node *&self, uint8_t index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fixMaxVersion(Node *self) {
|
||||||
|
for (;;) {
|
||||||
|
int64_t result = std::numeric_limits<int64_t>::lowest();
|
||||||
|
if (self->entryPresent) {
|
||||||
|
result = std::max(result, self->entry.pointVersion);
|
||||||
|
result = std::max(result, self->entry.rangeVersion);
|
||||||
|
}
|
||||||
|
for (int i = getChildGeq(self, 0); i >= 0; i = getChildGeq(self, i + 1)) {
|
||||||
|
result = std::max(result, getChildExists(self, i)->maxVersion);
|
||||||
|
}
|
||||||
|
if (self->maxVersion == result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self->maxVersion = result;
|
||||||
|
if (self->parent == nullptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self = self->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Precondition - an entry for index must exist in the node
|
// Precondition - an entry for index must exist in the node
|
||||||
void eraseChild(Node *self, uint8_t index) {
|
void eraseChild(Node *self, uint8_t index) {
|
||||||
free(getChildExists(self, index));
|
free(getChildExists(self, index));
|
||||||
@@ -814,21 +835,6 @@ void destroyTree(Node *root) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void invalidateMax(Node *self) {
|
|
||||||
int64_t expectedMax = std::numeric_limits<int64_t>::lowest();
|
|
||||||
if (self->entryPresent) {
|
|
||||||
expectedMax = std::max(expectedMax, self->entry.pointVersion);
|
|
||||||
expectedMax = std::max(expectedMax, self->entry.rangeVersion);
|
|
||||||
}
|
|
||||||
for (int i = getChildGeq(self, 0); i >= 0; i = getChildGeq(self, i + 1)) {
|
|
||||||
expectedMax = std::max(expectedMax, getChildExists(self, i)->maxVersion);
|
|
||||||
}
|
|
||||||
self->maxVersion = expectedMax;
|
|
||||||
if (self->parent != nullptr) {
|
|
||||||
invalidateMax(self->parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||||
void check(const ReadRange *reads, Result *result, int count) const {
|
void check(const ReadRange *reads, Result *result, int count) const {
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
@@ -858,33 +864,54 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
const auto &w = writes[i];
|
const auto &w = writes[i];
|
||||||
if (w.end.len > 0) {
|
if (w.end.len > 0) {
|
||||||
auto *n = insert(&root, std::span<const uint8_t>(w.end.p, w.end.len),
|
auto *begin =
|
||||||
std::numeric_limits<int64_t>::lowest());
|
insert(&root, std::span<const uint8_t>(w.begin.p, w.begin.len),
|
||||||
if (!n->entryPresent) {
|
w.writeVersion);
|
||||||
auto *p = prevLogical(n);
|
|
||||||
assert(p != nullptr);
|
const bool insertedBegin = !std::exchange(begin->entryPresent, true);
|
||||||
n->entryPresent = true;
|
begin->entry.pointVersion = w.writeVersion;
|
||||||
n->entry.pointVersion = p->entry.rangeVersion;
|
|
||||||
n->entry.rangeVersion = p->entry.rangeVersion;
|
auto *end = insert(&root, std::span<const uint8_t>(w.end.p, w.end.len),
|
||||||
|
std::numeric_limits<int64_t>::lowest());
|
||||||
|
|
||||||
|
const bool insertedEnd = !std::exchange(end->entryPresent, true);
|
||||||
|
if (insertedEnd) {
|
||||||
|
// begin may have been invalidated
|
||||||
|
auto iter =
|
||||||
|
lastLeq(root, std::span<const uint8_t>(w.begin.p, w.begin.len));
|
||||||
|
assert(iter.cmp == 0);
|
||||||
|
begin = iter.n;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *end = n;
|
if (insertedBegin) {
|
||||||
n = insert(&root, std::span<const uint8_t>(w.begin.p, w.begin.len),
|
auto *p = prevLogical(begin);
|
||||||
std::numeric_limits<int64_t>::lowest());
|
assert(p != nullptr);
|
||||||
auto *begin = n;
|
begin->entry.rangeVersion = p->entry.rangeVersion;
|
||||||
n->entryPresent = true;
|
}
|
||||||
n->entry.pointVersion = w.writeVersion;
|
|
||||||
n->entry.rangeVersion = w.writeVersion;
|
if (insertedEnd) {
|
||||||
for (n = nextLogical(n); n != end;) {
|
auto *p = prevLogical(end);
|
||||||
auto *old = n;
|
assert(p != nullptr);
|
||||||
n = nextLogical(n);
|
end->entryPresent = true;
|
||||||
|
end->entry.pointVersion = p->entry.rangeVersion;
|
||||||
|
end->entry.rangeVersion = p->entry.rangeVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
begin->entry.rangeVersion = w.writeVersion;
|
||||||
|
|
||||||
|
for (begin = nextLogical(begin); begin != end;) {
|
||||||
|
auto *old = begin;
|
||||||
|
begin = nextLogical(begin);
|
||||||
old->entryPresent = false;
|
old->entryPresent = false;
|
||||||
|
fixMaxVersion(old);
|
||||||
if (old->numChildren == 0 && old->parent != nullptr) {
|
if (old->numChildren == 0 && old->parent != nullptr) {
|
||||||
eraseChild(old->parent, old->parentsIndex);
|
eraseChild(old->parent, old->parentsIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
invalidateMax(begin);
|
|
||||||
invalidateMax(end);
|
if (insertedEnd) {
|
||||||
|
fixMaxVersion(end);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
auto *n =
|
auto *n =
|
||||||
insert(&root, std::span<const uint8_t>(w.begin.p, w.begin.len),
|
insert(&root, std::span<const uint8_t>(w.begin.p, w.begin.len),
|
||||||
@@ -1175,6 +1202,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
|
fprintf(stderr, "Check correctness\n");
|
||||||
|
#endif
|
||||||
bool success = checkCorrectness(driver.cs.root, driver.refImpl);
|
bool success = checkCorrectness(driver.cs.root, driver.refImpl);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
debugPrintDot(stdout, driver.cs.root);
|
debugPrintDot(stdout, driver.cs.root);
|
||||||
|
Reference in New Issue
Block a user