Compare commits
8
Commits
v0.0.9
..
79410d071f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79410d071f | ||
|
|
1fcca6450d | ||
|
|
55271ad06c | ||
|
|
e675612599 | ||
|
|
42b5d50492 | ||
|
|
6394995def | ||
|
|
c649bc7964 | ||
|
|
ec85a06d01 |
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.18)
|
cmake_minimum_required(VERSION 3.18)
|
||||||
project(
|
project(
|
||||||
conflict-set
|
conflict-set
|
||||||
VERSION 0.0.9
|
VERSION 0.0.10
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
"A data structure for optimistic concurrency control on ranges of bitwise-lexicographically-ordered keys."
|
"A data structure for optimistic concurrency control on ranges of bitwise-lexicographically-ordered keys."
|
||||||
HOMEPAGE_URL "https://git.weaselab.dev/weaselab/conflict-set"
|
HOMEPAGE_URL "https://git.weaselab.dev/weaselab/conflict-set"
|
||||||
|
|||||||
+35
-19
@@ -729,6 +729,8 @@ struct WriteContext {
|
|||||||
double entries_inserted_accum = 0;
|
double entries_inserted_accum = 0;
|
||||||
double nodes_allocated_accum = 0;
|
double nodes_allocated_accum = 0;
|
||||||
double nodes_released_accum = 0;
|
double nodes_released_accum = 0;
|
||||||
|
double point_writes_accum = 0;
|
||||||
|
double range_writes_accum = 0;
|
||||||
template <class T> T *allocate(int c) {
|
template <class T> T *allocate(int c) {
|
||||||
++nodes_allocated_accum;
|
++nodes_allocated_accum;
|
||||||
if constexpr (std::is_same_v<T, Node0>) {
|
if constexpr (std::is_same_v<T, Node0>) {
|
||||||
@@ -2949,6 +2951,7 @@ void destroyTree(Node *root) {
|
|||||||
void addPointWrite(Node *&root, std::span<const uint8_t> key,
|
void addPointWrite(Node *&root, std::span<const uint8_t> key,
|
||||||
InternalVersionT writeVersion, WriteContext *tls,
|
InternalVersionT writeVersion, WriteContext *tls,
|
||||||
ConflictSet::Impl *impl) {
|
ConflictSet::Impl *impl) {
|
||||||
|
++tls->point_writes_accum;
|
||||||
auto *n = insert<true>(&root, key, writeVersion, tls, impl);
|
auto *n = insert<true>(&root, key, writeVersion, tls, impl);
|
||||||
if (!n->entryPresent) {
|
if (!n->entryPresent) {
|
||||||
++tls->entries_inserted_accum;
|
++tls->entries_inserted_accum;
|
||||||
@@ -2978,6 +2981,7 @@ void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
|||||||
end.back() == 0) {
|
end.back() == 0) {
|
||||||
return addPointWrite(root, begin, writeVersion, tls, impl);
|
return addPointWrite(root, begin, writeVersion, tls, impl);
|
||||||
}
|
}
|
||||||
|
++tls->range_writes_accum;
|
||||||
const bool beginIsPrefix = lcp == int(begin.size());
|
const bool beginIsPrefix = lcp == int(begin.size());
|
||||||
auto remaining = begin.subspan(0, lcp);
|
auto remaining = begin.subspan(0, lcp);
|
||||||
|
|
||||||
@@ -3200,8 +3204,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double write_byte_accum = 0;
|
double write_byte_accum = 0;
|
||||||
int point_writes_accum = 0;
|
|
||||||
int range_writes_accum = 0;
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
const auto &w = writes[i];
|
const auto &w = writes[i];
|
||||||
write_byte_accum += w.begin.len + w.end.len;
|
write_byte_accum += w.begin.len + w.end.len;
|
||||||
@@ -3209,19 +3211,17 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
auto end = std::span<const uint8_t>(w.end.p, w.end.len);
|
auto end = std::span<const uint8_t>(w.end.p, w.end.len);
|
||||||
if (w.end.len > 0) {
|
if (w.end.len > 0) {
|
||||||
keyUpdates += 3;
|
keyUpdates += 3;
|
||||||
++range_writes_accum;
|
|
||||||
addWriteRange(root, begin, end, InternalVersionT(writeVersion), &tls,
|
addWriteRange(root, begin, end, InternalVersionT(writeVersion), &tls,
|
||||||
this);
|
this);
|
||||||
} else {
|
} else {
|
||||||
keyUpdates += 2;
|
keyUpdates += 2;
|
||||||
++point_writes_accum;
|
|
||||||
addPointWrite(root, begin, InternalVersionT(writeVersion), &tls, this);
|
addPointWrite(root, begin, InternalVersionT(writeVersion), &tls, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_bytes.set(totalBytes);
|
memory_bytes.set(totalBytes);
|
||||||
point_writes_total.add(point_writes_accum);
|
point_writes_total.add(std::exchange(tls.point_writes_accum, 0));
|
||||||
range_writes_total.add(range_writes_accum);
|
range_writes_total.add(std::exchange(tls.range_writes_accum, 0));
|
||||||
nodes_allocated_total.add(std::exchange(tls.nodes_allocated_accum, 0));
|
nodes_allocated_total.add(std::exchange(tls.nodes_allocated_accum, 0));
|
||||||
nodes_released_total.add(std::exchange(tls.nodes_released_accum, 0));
|
nodes_released_total.add(std::exchange(tls.nodes_released_accum, 0));
|
||||||
entries_inserted_total.add(std::exchange(tls.entries_inserted_accum, 0));
|
entries_inserted_total.add(std::exchange(tls.entries_inserted_accum, 0));
|
||||||
@@ -3928,7 +3928,7 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion,
|
|||||||
bool &success, ConflictSet::Impl *impl) {
|
bool &success, ConflictSet::Impl *impl) {
|
||||||
checkVersionsGeqOldestExtant(node,
|
checkVersionsGeqOldestExtant(node,
|
||||||
InternalVersionT(impl->oldestExtantVersion));
|
InternalVersionT(impl->oldestExtantVersion));
|
||||||
auto expected = InternalVersionT::zero;
|
auto expected = oldestVersion;
|
||||||
if (node->entryPresent) {
|
if (node->entryPresent) {
|
||||||
expected = std::max(expected, node->entry.pointVersion);
|
expected = std::max(expected, node->entry.pointVersion);
|
||||||
}
|
}
|
||||||
@@ -4151,26 +4151,42 @@ int main(void) { printTree(); }
|
|||||||
|
|
||||||
#ifdef ENABLE_FUZZ
|
#ifdef ENABLE_FUZZ
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||||
TestDriver<ConflictSet::Impl> driver{data, size};
|
Arbitrary arbitrary({data, size});
|
||||||
|
TestDriver<ConflictSet::Impl> driver1{arbitrary};
|
||||||
|
TestDriver<ConflictSet::Impl> driver2{arbitrary};
|
||||||
|
|
||||||
|
bool done1 = false;
|
||||||
|
bool done2 = false;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bool done = driver.next();
|
if (!done1) {
|
||||||
if (!driver.ok) {
|
done1 = driver1.next();
|
||||||
debugPrintDot(stdout, driver.cs.root, &driver.cs);
|
if (!driver1.ok) {
|
||||||
|
debugPrintDot(stdout, driver1.cs.root, &driver1.cs);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
if (!checkCorrectness(driver1.cs.root, driver1.cs.oldestVersion,
|
||||||
fprintf(stderr, "Check correctness\n");
|
&driver1.cs)) {
|
||||||
#endif
|
debugPrintDot(stdout, driver1.cs.root, &driver1.cs);
|
||||||
bool success =
|
|
||||||
checkCorrectness(driver.cs.root, driver.cs.oldestVersion, &driver.cs);
|
|
||||||
if (!success) {
|
|
||||||
debugPrintDot(stdout, driver.cs.root, &driver.cs);
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
if (done) {
|
}
|
||||||
|
if (!done2) {
|
||||||
|
done2 = driver2.next();
|
||||||
|
if (!driver2.ok) {
|
||||||
|
debugPrintDot(stdout, driver2.cs.root, &driver2.cs);
|
||||||
|
fflush(stdout);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (!checkCorrectness(driver2.cs.root, driver2.cs.oldestVersion,
|
||||||
|
&driver2.cs)) {
|
||||||
|
debugPrintDot(stdout, driver2.cs.root, &driver2.cs);
|
||||||
|
fflush(stdout);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (done1 && done2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-55
@@ -580,11 +580,14 @@ namespace {
|
|||||||
|
|
||||||
template <class ConflictSetImpl, bool kEnableAssertions = true>
|
template <class ConflictSetImpl, bool kEnableAssertions = true>
|
||||||
struct TestDriver {
|
struct TestDriver {
|
||||||
Arbitrary arbitrary;
|
Arbitrary *arbitrary;
|
||||||
explicit TestDriver(const uint8_t *data, size_t size)
|
explicit TestDriver(Arbitrary &a) : arbitrary(&a) {
|
||||||
: arbitrary({data, size}) {}
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
|
fprintf(stderr, "%p Initial version: {%" PRId64 "}\n", this, writeVersion);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int64_t oldestVersion = arbitrary.next();
|
int64_t oldestVersion = arbitrary->next();
|
||||||
int64_t writeVersion = oldestVersion;
|
int64_t writeVersion = oldestVersion;
|
||||||
ConflictSetImpl cs{oldestVersion};
|
ConflictSetImpl cs{oldestVersion};
|
||||||
ReferenceImpl refImpl{oldestVersion};
|
ReferenceImpl refImpl{oldestVersion};
|
||||||
@@ -593,33 +596,34 @@ struct TestDriver {
|
|||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
const int prefixLen = arbitrary.bounded(512);
|
const int prefixLen = arbitrary->bounded(512);
|
||||||
const int prefixByte = arbitrary.randT<uint8_t>();
|
const int prefixByte = arbitrary->randT<uint8_t>();
|
||||||
|
|
||||||
// Call until it returns true, for "done". Check internal invariants etc
|
// Call until it returns true, for "done". Check internal invariants etc
|
||||||
// between calls to next.
|
// between calls to next.
|
||||||
bool next() {
|
bool next() {
|
||||||
assert(cs.getBytes() >= 0);
|
assert(cs.getBytes() >= 0);
|
||||||
if (!arbitrary.hasEntropy()) {
|
if (!arbitrary->hasEntropy()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Arena arena;
|
Arena arena;
|
||||||
{
|
{
|
||||||
int numPointWrites = arbitrary.bounded(100);
|
int numPointWrites = arbitrary->bounded(100);
|
||||||
int numRangeWrites = arbitrary.bounded(100);
|
int numRangeWrites = arbitrary->bounded(100);
|
||||||
int64_t v = (writeVersion += arbitrary.bounded(10) ? arbitrary.bounded(10)
|
int64_t v =
|
||||||
: arbitrary.next());
|
(writeVersion +=
|
||||||
|
arbitrary->bounded(10) ? arbitrary->bounded(10) : arbitrary->next());
|
||||||
auto *writes =
|
auto *writes =
|
||||||
new (arena) ConflictSet::WriteRange[numPointWrites + numRangeWrites];
|
new (arena) ConflictSet::WriteRange[numPointWrites + numRangeWrites];
|
||||||
auto keys = set<std::string_view>(arena);
|
auto keys = set<std::string_view>(arena);
|
||||||
while (int(keys.size()) < numPointWrites + numRangeWrites * 2) {
|
while (int(keys.size()) < numPointWrites + numRangeWrites * 2) {
|
||||||
if (!arbitrary.hasEntropy()) {
|
if (!arbitrary->hasEntropy()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int keyLen = prefixLen + arbitrary.bounded(kMaxKeySuffixLen);
|
int keyLen = prefixLen + arbitrary->bounded(kMaxKeySuffixLen);
|
||||||
auto *begin = new (arena) uint8_t[keyLen];
|
auto *begin = new (arena) uint8_t[keyLen];
|
||||||
memset(begin, prefixByte, prefixLen);
|
memset(begin, prefixByte, prefixLen);
|
||||||
arbitrary.randomBytes(begin + prefixLen, keyLen - prefixLen);
|
arbitrary->randomBytes(begin + prefixLen, keyLen - prefixLen);
|
||||||
keys.insert(std::string_view((const char *)begin, keyLen));
|
keys.insert(std::string_view((const char *)begin, keyLen));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,7 +633,7 @@ struct TestDriver {
|
|||||||
rangesRemaining = numRangeWrites;
|
rangesRemaining = numRangeWrites;
|
||||||
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
|
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
|
||||||
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
|
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
|
||||||
? bool(arbitrary.bounded(2))
|
? bool(arbitrary->bounded(2))
|
||||||
: pointsRemaining > 0;
|
: pointsRemaining > 0;
|
||||||
if (pointRead) {
|
if (pointRead) {
|
||||||
assert(pointsRemaining > 0);
|
assert(pointsRemaining > 0);
|
||||||
@@ -648,33 +652,20 @@ struct TestDriver {
|
|||||||
++iter;
|
++iter;
|
||||||
--rangesRemaining;
|
--rangesRemaining;
|
||||||
}
|
}
|
||||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
|
||||||
if (writes[i].end.len == 0) {
|
|
||||||
fprintf(stderr, "Write: {%s}\n", printable(writes[i].begin).c_str());
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Write: [%s, %s)\n",
|
|
||||||
printable(writes[i].begin).c_str(),
|
|
||||||
printable(writes[i].end).c_str());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
assert(iter == keys.end());
|
assert(iter == keys.end());
|
||||||
assert(i == numPointWrites + numRangeWrites);
|
assert(i == numPointWrites + numRangeWrites);
|
||||||
|
|
||||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
|
||||||
fprintf(stderr, "Write @ %" PRId64 "\n", v);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Test non-canonical writes
|
// Test non-canonical writes
|
||||||
if (numPointWrites > 0) {
|
if (numPointWrites > 0) {
|
||||||
int overlaps = arbitrary.bounded(numPointWrites);
|
int overlaps = arbitrary->bounded(numPointWrites);
|
||||||
for (int i = 0; i < numPointWrites + numRangeWrites && overlaps > 0;
|
for (int i = 0; i < numPointWrites + numRangeWrites && overlaps > 0;
|
||||||
++i) {
|
++i) {
|
||||||
if (writes[i].end.len == 0) {
|
if (writes[i].end.len == 0) {
|
||||||
int keyLen = prefixLen + arbitrary.bounded(kMaxKeySuffixLen);
|
int keyLen = prefixLen + arbitrary->bounded(kMaxKeySuffixLen);
|
||||||
auto *begin = new (arena) uint8_t[keyLen];
|
auto *begin = new (arena) uint8_t[keyLen];
|
||||||
memset(begin, prefixByte, prefixLen);
|
memset(begin, prefixByte, prefixLen);
|
||||||
arbitrary.randomBytes(begin + prefixLen, keyLen - prefixLen);
|
arbitrary->randomBytes(begin + prefixLen, keyLen - prefixLen);
|
||||||
writes[i].end.len = keyLen;
|
writes[i].end.len = keyLen;
|
||||||
writes[i].end.p = begin;
|
writes[i].end.p = begin;
|
||||||
auto c =
|
auto c =
|
||||||
@@ -692,10 +683,10 @@ struct TestDriver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (arbitrary.bounded(2)) {
|
if (arbitrary->bounded(2)) {
|
||||||
// Shuffle writes
|
// Shuffle writes
|
||||||
for (int i = numPointWrites + numRangeWrites - 1; i > 0; --i) {
|
for (int i = numPointWrites + numRangeWrites - 1; i > 0; --i) {
|
||||||
int j = arbitrary.bounded(i + 1);
|
int j = arbitrary->bounded(i + 1);
|
||||||
if (i != j) {
|
if (i != j) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(writes[i], writes[j]);
|
swap(writes[i], writes[j]);
|
||||||
@@ -704,7 +695,7 @@ struct TestDriver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oldestVersion +=
|
oldestVersion +=
|
||||||
arbitrary.bounded(10) ? arbitrary.bounded(10) : arbitrary.next();
|
arbitrary->bounded(10) ? arbitrary->bounded(10) : arbitrary->next();
|
||||||
oldestVersion = std::min(oldestVersion, writeVersion);
|
oldestVersion = std::min(oldestVersion, writeVersion);
|
||||||
|
|
||||||
#ifdef THREAD_TEST
|
#ifdef THREAD_TEST
|
||||||
@@ -721,6 +712,20 @@ struct TestDriver {
|
|||||||
ready.wait();
|
ready.wait();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
|
for (int i = 0; i < numPointWrites + numRangeWrites; ++i) {
|
||||||
|
if (writes[i].end.len == 0) {
|
||||||
|
fprintf(stderr, "%p Write: {%s}\n", this,
|
||||||
|
printable(writes[i].begin).c_str());
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%p Write: [%s, %s)\n", this,
|
||||||
|
printable(writes[i].begin).c_str(),
|
||||||
|
printable(writes[i].end).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%p Write @ %" PRId64 "\n", this, v);
|
||||||
|
#endif
|
||||||
|
|
||||||
CALLGRIND_START_INSTRUMENTATION;
|
CALLGRIND_START_INSTRUMENTATION;
|
||||||
cs.addWrites(writes, numPointWrites + numRangeWrites, v);
|
cs.addWrites(writes, numPointWrites + numRangeWrites, v);
|
||||||
CALLGRIND_STOP_INSTRUMENTATION;
|
CALLGRIND_STOP_INSTRUMENTATION;
|
||||||
@@ -729,6 +734,10 @@ struct TestDriver {
|
|||||||
refImpl.addWrites(writes, numPointWrites + numRangeWrites, v);
|
refImpl.addWrites(writes, numPointWrites + numRangeWrites, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
|
fprintf(stderr, "%p Set oldest version: %" PRId64 "\n", this,
|
||||||
|
oldestVersion);
|
||||||
|
#endif
|
||||||
cs.setOldestVersion(oldestVersion);
|
cs.setOldestVersion(oldestVersion);
|
||||||
if constexpr (kEnableAssertions) {
|
if constexpr (kEnableAssertions) {
|
||||||
refImpl.setOldestVersion(oldestVersion);
|
refImpl.setOldestVersion(oldestVersion);
|
||||||
@@ -739,24 +748,24 @@ struct TestDriver {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int numPointReads = arbitrary.bounded(100);
|
int numPointReads = arbitrary->bounded(100);
|
||||||
int numRangeReads = arbitrary.bounded(100);
|
int numRangeReads = arbitrary->bounded(100);
|
||||||
|
|
||||||
int64_t v = std::max<int64_t>(writeVersion - (arbitrary.bounded(10)
|
int64_t v = std::max<int64_t>(writeVersion - (arbitrary->bounded(10)
|
||||||
? arbitrary.bounded(10)
|
? arbitrary->bounded(10)
|
||||||
: arbitrary.next()),
|
: arbitrary->next()),
|
||||||
0);
|
0);
|
||||||
auto *reads =
|
auto *reads =
|
||||||
new (arena) ConflictSet::ReadRange[numPointReads + numRangeReads];
|
new (arena) ConflictSet::ReadRange[numPointReads + numRangeReads];
|
||||||
auto keys = set<std::string_view>(arena);
|
auto keys = set<std::string_view>(arena);
|
||||||
while (int(keys.size()) < numPointReads + numRangeReads * 2) {
|
while (int(keys.size()) < numPointReads + numRangeReads * 2) {
|
||||||
if (!arbitrary.hasEntropy()) {
|
if (!arbitrary->hasEntropy()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int keyLen = prefixLen + arbitrary.bounded(kMaxKeySuffixLen);
|
int keyLen = prefixLen + arbitrary->bounded(kMaxKeySuffixLen);
|
||||||
auto *begin = new (arena) uint8_t[keyLen];
|
auto *begin = new (arena) uint8_t[keyLen];
|
||||||
memset(begin, prefixByte, prefixLen);
|
memset(begin, prefixByte, prefixLen);
|
||||||
arbitrary.randomBytes(begin + prefixLen, keyLen - prefixLen);
|
arbitrary->randomBytes(begin + prefixLen, keyLen - prefixLen);
|
||||||
keys.insert(std::string_view((const char *)begin, keyLen));
|
keys.insert(std::string_view((const char *)begin, keyLen));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,7 +774,7 @@ struct TestDriver {
|
|||||||
for (int pointsRemaining = numPointReads, rangesRemaining = numRangeReads;
|
for (int pointsRemaining = numPointReads, rangesRemaining = numRangeReads;
|
||||||
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
|
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
|
||||||
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
|
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
|
||||||
? bool(arbitrary.bounded(2))
|
? bool(arbitrary->bounded(2))
|
||||||
: pointsRemaining > 0;
|
: pointsRemaining > 0;
|
||||||
if (pointRead) {
|
if (pointRead) {
|
||||||
assert(pointsRemaining > 0);
|
assert(pointsRemaining > 0);
|
||||||
@@ -787,10 +796,10 @@ struct TestDriver {
|
|||||||
reads[i].readVersion = v;
|
reads[i].readVersion = v;
|
||||||
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
if (reads[i].end.len == 0) {
|
if (reads[i].end.len == 0) {
|
||||||
fprintf(stderr, "Read: {%s} @ %" PRId64 "\n",
|
fprintf(stderr, "%p Read: {%s} @ %" PRId64 "\n", this,
|
||||||
printable(reads[i].begin).c_str(), reads[i].readVersion);
|
printable(reads[i].begin).c_str(), reads[i].readVersion);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Read: [%s, %s) @ %" PRId64 "\n",
|
fprintf(stderr, "%p Read: [%s, %s) @ %" PRId64 "\n", this,
|
||||||
printable(reads[i].begin).c_str(),
|
printable(reads[i].begin).c_str(),
|
||||||
printable(reads[i].end).c_str(), reads[i].readVersion);
|
printable(reads[i].end).c_str(), reads[i].readVersion);
|
||||||
}
|
}
|
||||||
@@ -839,22 +848,25 @@ struct TestDriver {
|
|||||||
refImpl.check(reads, results2, numPointReads + numRangeReads);
|
refImpl.check(reads, results2, numPointReads + numRangeReads);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto compareResults = [reads](ConflictSet::Result *results1,
|
auto compareResults = [reads, this](ConflictSet::Result *results1,
|
||||||
ConflictSet::Result *results2, int count) {
|
ConflictSet::Result *results2,
|
||||||
|
int count) {
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
if (results1[i] != results2[i]) {
|
if (results1[i] != results2[i]) {
|
||||||
if (reads[i].end.len == 0) {
|
if (reads[i].end.len == 0) {
|
||||||
fprintf(stderr,
|
|
||||||
"Expected %s, got %s for read of {%s} at version %" PRId64
|
|
||||||
"\n",
|
|
||||||
resultToStr(results2[i]), resultToStr(results1[i]),
|
|
||||||
printable(reads[i].begin).c_str(), reads[i].readVersion);
|
|
||||||
} else {
|
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr,
|
stderr,
|
||||||
"Expected %s, got %s for read of [%s, %s) at version %" PRId64
|
"%p Expected %s, got %s for read of {%s} at version %" PRId64
|
||||||
"\n",
|
"\n",
|
||||||
resultToStr(results2[i]), resultToStr(results1[i]),
|
(void *)this, resultToStr(results2[i]),
|
||||||
|
resultToStr(results1[i]), printable(reads[i].begin).c_str(),
|
||||||
|
reads[i].readVersion);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%p Expected %s, got %s for read of [%s, %s) at version "
|
||||||
|
"%" PRId64 "\n",
|
||||||
|
(void *)this, resultToStr(results2[i]),
|
||||||
|
resultToStr(results1[i]),
|
||||||
printable(reads[i].begin).c_str(),
|
printable(reads[i].begin).c_str(),
|
||||||
printable(reads[i].end).c_str(), reads[i].readVersion);
|
printable(reads[i].end).c_str(), reads[i].readVersion);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -778,10 +778,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
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];
|
||||||
#if DEBUG_VERBOSE
|
|
||||||
printf("Write begin: %s\n", printable(w.begin).c_str());
|
|
||||||
fflush(stdout);
|
|
||||||
#endif
|
|
||||||
values[i * 2] = w.first;
|
values[i * 2] = w.first;
|
||||||
values[i * 2 + 1] = w.second;
|
values[i * 2 + 1] = w.second;
|
||||||
keyUpdates += 3;
|
keyUpdates += 3;
|
||||||
|
|||||||
+40
-7
@@ -13,18 +13,35 @@ int main(int argc, char **argv) {
|
|||||||
std::stringstream buffer;
|
std::stringstream buffer;
|
||||||
buffer << t.rdbuf();
|
buffer << t.rdbuf();
|
||||||
auto str = buffer.str();
|
auto str = buffer.str();
|
||||||
TestDriver<ConflictSet, !PERF_TEST> driver{(const uint8_t *)str.data(),
|
Arbitrary arbitrary({(const uint8_t *)str.data(), str.size()});
|
||||||
str.size()};
|
TestDriver<ConflictSet, !PERF_TEST> driver1{arbitrary};
|
||||||
while (!driver.next())
|
TestDriver<ConflictSet, !PERF_TEST> driver2{arbitrary};
|
||||||
;
|
bool done1 = false;
|
||||||
if (!driver.ok) {
|
bool done2 = false;
|
||||||
|
for (;;) {
|
||||||
|
if (!done1) {
|
||||||
|
done1 = driver1.next();
|
||||||
|
if (!driver1.ok) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (!done2) {
|
||||||
|
done2 = driver2.next();
|
||||||
|
if (!driver2.ok) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (done1 && done2) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
ConflictSet::MetricsV1 *metrics;
|
ConflictSet::MetricsV1 *metrics;
|
||||||
int metricsCount;
|
int metricsCount;
|
||||||
driver.cs.getMetricsV1(&metrics, &metricsCount);
|
driver1.cs.getMetricsV1(&metrics, &metricsCount);
|
||||||
printf("#################### METRICS FOR %s ####################\n",
|
printf("#################### METRICS for ConflictSet 1 for %s "
|
||||||
|
"####################\n",
|
||||||
argv[i]);
|
argv[i]);
|
||||||
for (int i = 0; i < metricsCount; ++i) {
|
for (int i = 0; i < metricsCount; ++i) {
|
||||||
printf("# HELP %s %s\n", metrics[i].name, metrics[i].help);
|
printf("# HELP %s %s\n", metrics[i].name, metrics[i].help);
|
||||||
@@ -34,4 +51,20 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
puts("");
|
puts("");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
ConflictSet::MetricsV1 *metrics;
|
||||||
|
int metricsCount;
|
||||||
|
driver2.cs.getMetricsV1(&metrics, &metricsCount);
|
||||||
|
printf("#################### METRICS for ConflictSet 2 for %s "
|
||||||
|
"####################\n",
|
||||||
|
argv[i]);
|
||||||
|
for (int i = 0; i < metricsCount; ++i) {
|
||||||
|
printf("# HELP %s %s\n", metrics[i].name, metrics[i].help);
|
||||||
|
printf("# TYPE %s %s\n", metrics[i].name,
|
||||||
|
metrics[i].type == metrics[i].Counter ? "counter" : "gauge");
|
||||||
|
printf("%s %g\n", metrics[i].name, metrics[i].getValue());
|
||||||
|
}
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
��
|
||||||
|
|
||||||
|
|
||||||
|
2
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
�
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user