11 Commits

Author SHA1 Message Date
andrew 2b11650589 Update aarch64 import symbols
Tests / Clang total: 1499, passed: 1499
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1497, passed: 1497
Tests / SIMD fallback total: 1499, passed: 1499
Tests / Release [gcc] total: 1499, passed: 1499
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1117, passed: 1117
Tests / Coverage total: 1126, passed: 1126
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 98.86% (1735/1755) * Branch Coverage: 64.08% (1525/2380) * Complexity Density: 0.00 * Lines of Code: 1755 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-07-31 17:34:30 -07:00
andrew fce998460f Use int64_t internally for metrics
Tests / Clang total: 1499, passed: 1499
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1497, passed: 1497
Tests / SIMD fallback total: 1499, passed: 1499
Tests / Release [gcc] total: 1499, passed: 1499
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1117, failed: 1, passed: 1116
Tests / Coverage total: 1126, passed: 1126
weaselab/conflict-set/pipeline/head There was a failure building this commit
So we can use fetch_add
2024-07-31 14:41:42 -07:00
andrew 6da3125719 Remove everything wasm-related
Tests / Clang total: 1499, passed: 1499
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1497, passed: 1497
Tests / SIMD fallback total: 1499, passed: 1499
Tests / Release [gcc] total: 1499, passed: 1499
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1117, passed: 1117
Tests / Coverage total: 1126, passed: 1126
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 98.81% (1738/1759) * Branch Coverage: 64.05% (1527/2384) * Complexity Density: 0.00 * Lines of Code: 1759 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
I'm not interested in supporting wasm at this time
2024-07-31 14:04:10 -07:00
andrew 79410d071f Add accidentally-deleted corpus back
Tests / Clang total: 1499, passed: 1499
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1497, passed: 1497
Tests / SIMD fallback total: 1499, passed: 1499
Tests / Release [gcc] total: 1499, passed: 1499
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1117, passed: 1117
Tests / Coverage total: 1126, passed: 1126
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 98.81% (1738/1759) * Branch Coverage: 64.05% (1527/2384) * Complexity Density: 0.00 * Lines of Code: 1759 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-07-26 14:57:04 -07:00
andrew 1fcca6450d Fix point writes accounting
Previously it wouldn't count a singleton range write
2024-07-26 14:41:54 -07:00
andrew 55271ad06c Update corpus
Tests / Clang total: 15, passed: 15
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 13, passed: 13
Tests / SIMD fallback total: 15, passed: 15
Tests / Release [gcc] total: 15, passed: 15
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 4, passed: 4
Tests / Coverage total: 13, passed: 13
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 66.27% (1167/1761) * Branch Coverage: 18.79% (448/2384) * Complexity Density: 0.00 * Lines of Code: 1761 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
To match new "interleaving" test setup
2024-07-23 16:54:03 -07:00
andrew e675612599 Suppress some warnings in test code 2024-07-23 16:50:02 -07:00
andrew 42b5d50492 Update DEBUG_VERBOSE for interleaving conflict sets in test 2024-07-23 15:44:29 -07:00
andrew 6394995def Add a test where the "zero" bug causes an incorrect commit 2024-07-23 14:39:45 -07:00
andrew c649bc7964 Interleave calls for two conflict sets in tests 2024-07-23 11:12:02 -07:00
andrew ec85a06d01 Bump version
Tests / Clang total: 1534, passed: 1534
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1532, passed: 1532
Tests / SIMD fallback total: 1534, passed: 1534
Tests / Release [gcc] total: 1534, passed: 1534
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1144, passed: 1144
Tests / Coverage total: 1152, passed: 1152
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 98.81% (1740/1761) * Branch Coverage: 64.01% (1526/2384) * Complexity Density: 0.00 * Lines of Code: 1761 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-07-22 17:25:38 -07:00
758 changed files with 237 additions and 209 deletions
+33 -55
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.18)
project(
conflict-set
VERSION 0.0.9
VERSION 0.0.10
DESCRIPTION
"A data structure for optimistic concurrency control on ranges of bitwise-lexicographically-ordered keys."
HOMEPAGE_URL "https://git.weaselab.dev/weaselab/conflict-set"
@@ -19,12 +19,6 @@ include(CheckCXXSourceCompiles)
set(DEFAULT_BUILD_TYPE "Release")
if(EMSCRIPTEN OR CMAKE_SYSTEM_NAME STREQUAL WASI)
set(WASM ON)
else()
set(WASM OFF)
endif()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(
STATUS
@@ -81,15 +75,6 @@ if(EMSCRIPTEN)
endif()
if(NOT USE_SIMD_FALLBACK)
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_FLAGS -msimd128)
check_include_file_cxx("wasm_simd128.h" HAS_WASM_SIMD)
if(HAS_WASM_SIMD)
add_compile_options(-msimd128)
add_compile_definitions(HAS_WASM_SIMD)
endif()
cmake_pop_check_state()
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_FLAGS -mavx)
check_include_file_cxx("immintrin.h" HAS_AVX)
@@ -162,47 +147,40 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
file(GLOB CORPUS_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/corpus/*)
# extra testing that relies on shared libraries, which aren't available with
# wasm
if(NOT WASM)
# Shared library version of FoundationDB's skip list implementation
add_library(skip_list SHARED SkipList.cpp)
target_compile_options(skip_list PRIVATE -fno-exceptions
-fvisibility=hidden)
target_include_directories(skip_list
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
set_target_properties(
skip_list PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}/skip_list")
set_target_properties(skip_list PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(
skip_list PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION
${PROJECT_VERSION_MAJOR})
# Shared library version of FoundationDB's skip list implementation
add_library(skip_list SHARED SkipList.cpp)
target_compile_options(skip_list PRIVATE -fno-exceptions -fvisibility=hidden)
target_include_directories(skip_list
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
set_target_properties(
skip_list PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}/skip_list")
set_target_properties(skip_list PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(skip_list PROPERTIES VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})
# Shared library version of a std::unordered_map-based conflict set (point
# queries only)
add_library(hash_table SHARED HashTable.cpp)
target_compile_options(hash_table PRIVATE -fno-exceptions
-fvisibility=hidden)
target_include_directories(hash_table
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
set_target_properties(
hash_table PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}/hash_table")
set_target_properties(hash_table PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(
hash_table PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION
${PROJECT_VERSION_MAJOR})
# Shared library version of a std::unordered_map-based conflict set (point
# queries only)
add_library(hash_table SHARED HashTable.cpp)
target_compile_options(hash_table PRIVATE -fno-exceptions -fvisibility=hidden)
target_include_directories(hash_table
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
set_target_properties(
hash_table PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}/hash_table")
set_target_properties(hash_table PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(
hash_table PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION
${PROJECT_VERSION_MAJOR})
add_executable(driver_skip_list TestDriver.cpp)
target_compile_options(driver_skip_list PRIVATE ${TEST_FLAGS})
target_link_libraries(driver_skip_list PRIVATE skip_list)
add_executable(driver_skip_list TestDriver.cpp)
target_compile_options(driver_skip_list PRIVATE ${TEST_FLAGS})
target_link_libraries(driver_skip_list PRIVATE skip_list)
foreach(TEST ${CORPUS_TESTS})
get_filename_component(hash ${TEST} NAME)
add_test(NAME skip_list_${hash} COMMAND driver_skip_list ${TEST})
endforeach()
endif()
foreach(TEST ${CORPUS_TESTS})
get_filename_component(hash ${TEST} NAME)
add_test(NAME skip_list_${hash} COMMAND driver_skip_list ${TEST})
endforeach()
# ad hoc testing
add_executable(conflict_set_main ConflictSet.cpp)
@@ -320,7 +298,7 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
add_test(NAME conflict_set_cxx_api_test COMMAND conflict_set_cxx_api_test)
# symbol visibility tests
if(NOT WASM AND NOT CMAKE_BUILD_TYPE STREQUAL Debug)
if(NOT CMAKE_BUILD_TYPE STREQUAL Debug)
if(APPLE)
set(symbol_exports ${CMAKE_CURRENT_SOURCE_DIR}/apple-symbol-exports.txt)
set(symbol_imports ${CMAKE_CURRENT_SOURCE_DIR}/apple-symbol-imports.txt)
+63 -70
View File
@@ -18,6 +18,7 @@ limitations under the License.
#include "Internal.h"
#include <algorithm>
#include <atomic>
#include <bit>
#include <cassert>
#include <compare>
@@ -552,7 +553,7 @@ struct Metric {
const char *name;
const char *help;
ConflictSet::MetricsV1::Type type;
std::atomic<double> value;
std::atomic<int64_t> value;
protected:
Metric(ConflictSet::Impl *impl, const char *name, const char *help,
@@ -563,7 +564,7 @@ struct Gauge : private Metric {
Gauge(ConflictSet::Impl *impl, const char *name, const char *help)
: Metric(impl, name, help, ConflictSet::MetricsV1::Gauge) {}
void set(double value) {
void set(int64_t value) {
this->value.store(value, std::memory_order_relaxed);
}
};
@@ -573,17 +574,10 @@ struct Counter : private Metric {
: Metric(impl, name, help, ConflictSet::MetricsV1::Counter) {}
// Expensive. Accumulate locally and then call add instead of repeatedly
// calling add.
void add(double value) {
void add(int64_t value) {
assert(value >= 0);
static_assert(std::atomic<double>::is_always_lock_free);
double old = this->value.load(std::memory_order_relaxed);
for (;;) {
double newVal = old + value;
if (this->value.compare_exchange_weak(old, newVal,
std::memory_order_relaxed)) {
break;
}
}
static_assert(std::atomic<int64_t>::is_always_lock_free);
this->value.fetch_add(value, std::memory_order_relaxed);
}
};
@@ -708,27 +702,29 @@ size_t Node::size() const {
// A type that's plumbed along the check call tree. Lifetime ends after each
// check call.
struct ReadContext {
double point_read_accum = 0;
double prefix_read_accum = 0;
double range_read_accum = 0;
double point_read_short_circuit_accum = 0;
double prefix_read_short_circuit_accum = 0;
double range_read_short_circuit_accum = 0;
double point_read_iterations_accum = 0;
double prefix_read_iterations_accum = 0;
double range_read_iterations_accum = 0;
double range_read_node_scan_accum = 0;
int64_t point_read_accum = 0;
int64_t prefix_read_accum = 0;
int64_t range_read_accum = 0;
int64_t point_read_short_circuit_accum = 0;
int64_t prefix_read_short_circuit_accum = 0;
int64_t range_read_short_circuit_accum = 0;
int64_t point_read_iterations_accum = 0;
int64_t prefix_read_iterations_accum = 0;
int64_t range_read_iterations_accum = 0;
int64_t range_read_node_scan_accum = 0;
ConflictSet::Impl *impl;
};
// A type that's plumbed along the non-const call tree. Same lifetime as
// ConflictSet::Impl
struct WriteContext {
double entries_erased_accum = 0;
double insert_iterations_accum = 0;
double entries_inserted_accum = 0;
double nodes_allocated_accum = 0;
double nodes_released_accum = 0;
int64_t entries_erased_accum = 0;
int64_t insert_iterations_accum = 0;
int64_t entries_inserted_accum = 0;
int64_t nodes_allocated_accum = 0;
int64_t nodes_released_accum = 0;
int64_t point_writes_accum = 0;
int64_t range_writes_accum = 0;
template <class T> T *allocate(int c) {
++nodes_allocated_accum;
if constexpr (std::is_same_v<T, Node0>) {
@@ -2949,6 +2945,7 @@ void destroyTree(Node *root) {
void addPointWrite(Node *&root, std::span<const uint8_t> key,
InternalVersionT writeVersion, WriteContext *tls,
ConflictSet::Impl *impl) {
++tls->point_writes_accum;
auto *n = insert<true>(&root, key, writeVersion, tls, impl);
if (!n->entryPresent) {
++tls->entries_inserted_accum;
@@ -2978,6 +2975,7 @@ void addWriteRange(Node *&root, std::span<const uint8_t> begin,
end.back() == 0) {
return addPointWrite(root, begin, writeVersion, tls, impl);
}
++tls->range_writes_accum;
const bool beginIsPrefix = lcp == int(begin.size());
auto remaining = begin.subspan(0, lcp);
@@ -3118,21 +3116,15 @@ Node *firstGeqPhysical(Node *n, const std::span<const uint8_t> key) {
}
}
#define MEASURE_CHECK_CPU_TIME 0
struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
void check(const ReadRange *reads, Result *result, int count) {
#if MEASURE_CHECK_CPU_TIME
timespec ts_begin;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts_begin);
#endif
ReadContext tls;
tls.impl = this;
int commits_accum = 0;
int conflicts_accum = 0;
int too_olds_accum = 0;
double check_byte_accum = 0;
int64_t check_byte_accum = 0;
for (int i = 0; i < count; ++i) {
const auto &r = reads[i];
check_byte_accum += r.begin.len + r.end.len;
@@ -3167,13 +3159,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
conflicts_total.add(conflicts_accum);
too_olds_total.add(too_olds_accum);
check_bytes_total.add(check_byte_accum);
#if MEASURE_CHECK_CPU_TIME
timespec ts_end;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts_end);
check_cpu_seconds_total.add(
std::max<double>(0, (ts_end.tv_nsec * 1e-9 + ts_end.tv_sec) -
(ts_begin.tv_nsec * 1e-9 + ts_begin.tv_sec)));
#endif
}
void addWrites(const WriteRange *writes, int count, int64_t writeVersion) {
@@ -3199,9 +3184,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
gcScanStep(1000);
}
double write_byte_accum = 0;
int point_writes_accum = 0;
int range_writes_accum = 0;
int64_t write_byte_accum = 0;
for (int i = 0; i < count; ++i) {
const auto &w = writes[i];
write_byte_accum += w.begin.len + w.end.len;
@@ -3209,19 +3192,17 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
auto end = std::span<const uint8_t>(w.end.p, w.end.len);
if (w.end.len > 0) {
keyUpdates += 3;
++range_writes_accum;
addWriteRange(root, begin, end, InternalVersionT(writeVersion), &tls,
this);
} else {
keyUpdates += 2;
++point_writes_accum;
addPointWrite(root, begin, InternalVersionT(writeVersion), &tls, this);
}
}
memory_bytes.set(totalBytes);
point_writes_total.add(point_writes_accum);
range_writes_total.add(range_writes_accum);
point_writes_total.add(std::exchange(tls.point_writes_accum, 0));
range_writes_total.add(std::exchange(tls.range_writes_accum, 0));
nodes_allocated_total.add(std::exchange(tls.nodes_allocated_accum, 0));
nodes_released_total.add(std::exchange(tls.nodes_released_accum, 0));
entries_inserted_total.add(std::exchange(tls.entries_inserted_accum, 0));
@@ -3242,7 +3223,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
rootMaxVersion = std::max(rootMaxVersion, oldestVersion);
n = nextPhysical(n);
}
double set_oldest_iterations_accum = 0;
int64_t set_oldest_iterations_accum = 0;
for (; fuel > 0 && n != nullptr; ++set_oldest_iterations_accum) {
rezero(n, oldestVersion);
// The "make sure gc keeps up with writes" calculations assume that we're
@@ -3443,10 +3424,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
GAUGE(
oldest_extant_version,
"A lower bound on the lowest version associated with an existing entry");
#if MEASURE_CHECK_CPU_TIME
COUNTER(check_cpu_seconds_total,
"Total cpu seconds spent in a call to check");
#endif
// ==================== END METRICS DEFINITIONS ====================
#undef GAUGE
#undef COUNTER
@@ -3928,7 +3905,7 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion,
bool &success, ConflictSet::Impl *impl) {
checkVersionsGeqOldestExtant(node,
InternalVersionT(impl->oldestExtantVersion));
auto expected = InternalVersionT::zero;
auto expected = oldestVersion;
if (node->entryPresent) {
expected = std::max(expected, node->entry.pointVersion);
}
@@ -4151,26 +4128,42 @@ int main(void) { printTree(); }
#ifdef ENABLE_FUZZ
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 (;;) {
bool done = driver.next();
if (!driver.ok) {
debugPrintDot(stdout, driver.cs.root, &driver.cs);
fflush(stdout);
abort();
if (!done1) {
done1 = driver1.next();
if (!driver1.ok) {
debugPrintDot(stdout, driver1.cs.root, &driver1.cs);
fflush(stdout);
abort();
}
if (!checkCorrectness(driver1.cs.root, driver1.cs.oldestVersion,
&driver1.cs)) {
debugPrintDot(stdout, driver1.cs.root, &driver1.cs);
fflush(stdout);
abort();
}
}
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "Check correctness\n");
#endif
bool success =
checkCorrectness(driver.cs.root, driver.cs.oldestVersion, &driver.cs);
if (!success) {
debugPrintDot(stdout, driver.cs.root, &driver.cs);
fflush(stdout);
abort();
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 (done) {
if (done1 && done2) {
break;
}
}
+69 -57
View File
@@ -580,11 +580,14 @@ namespace {
template <class ConflictSetImpl, bool kEnableAssertions = true>
struct TestDriver {
Arbitrary arbitrary;
explicit TestDriver(const uint8_t *data, size_t size)
: arbitrary({data, size}) {}
Arbitrary *arbitrary;
explicit TestDriver(Arbitrary &a) : arbitrary(&a) {
#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;
ConflictSetImpl cs{oldestVersion};
ReferenceImpl refImpl{oldestVersion};
@@ -593,33 +596,34 @@ struct TestDriver {
bool ok = true;
const int prefixLen = arbitrary.bounded(512);
const int prefixByte = arbitrary.randT<uint8_t>();
const int prefixLen = arbitrary->bounded(512);
const int prefixByte = arbitrary->randT<uint8_t>();
// Call until it returns true, for "done". Check internal invariants etc
// between calls to next.
bool next() {
assert(cs.getBytes() >= 0);
if (!arbitrary.hasEntropy()) {
if (!arbitrary->hasEntropy()) {
return true;
}
Arena arena;
{
int numPointWrites = arbitrary.bounded(100);
int numRangeWrites = arbitrary.bounded(100);
int64_t v = (writeVersion += arbitrary.bounded(10) ? arbitrary.bounded(10)
: arbitrary.next());
int numPointWrites = arbitrary->bounded(100);
int numRangeWrites = arbitrary->bounded(100);
int64_t v =
(writeVersion +=
arbitrary->bounded(10) ? arbitrary->bounded(10) : arbitrary->next());
auto *writes =
new (arena) ConflictSet::WriteRange[numPointWrites + numRangeWrites];
auto keys = set<std::string_view>(arena);
while (int(keys.size()) < numPointWrites + numRangeWrites * 2) {
if (!arbitrary.hasEntropy()) {
if (!arbitrary->hasEntropy()) {
return true;
}
int keyLen = prefixLen + arbitrary.bounded(kMaxKeySuffixLen);
int keyLen = prefixLen + arbitrary->bounded(kMaxKeySuffixLen);
auto *begin = new (arena) uint8_t[keyLen];
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));
}
@@ -629,7 +633,7 @@ struct TestDriver {
rangesRemaining = numRangeWrites;
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
? bool(arbitrary.bounded(2))
? bool(arbitrary->bounded(2))
: pointsRemaining > 0;
if (pointRead) {
assert(pointsRemaining > 0);
@@ -648,33 +652,20 @@ struct TestDriver {
++iter;
--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(i == numPointWrites + numRangeWrites);
#if DEBUG_VERBOSE && !defined(NDEBUG)
fprintf(stderr, "Write @ %" PRId64 "\n", v);
#endif
// Test non-canonical writes
if (numPointWrites > 0) {
int overlaps = arbitrary.bounded(numPointWrites);
int overlaps = arbitrary->bounded(numPointWrites);
for (int i = 0; i < numPointWrites + numRangeWrites && overlaps > 0;
++i) {
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];
memset(begin, prefixByte, prefixLen);
arbitrary.randomBytes(begin + prefixLen, keyLen - prefixLen);
arbitrary->randomBytes(begin + prefixLen, keyLen - prefixLen);
writes[i].end.len = keyLen;
writes[i].end.p = begin;
auto c =
@@ -692,10 +683,10 @@ struct TestDriver {
}
}
}
if (arbitrary.bounded(2)) {
if (arbitrary->bounded(2)) {
// Shuffle writes
for (int i = numPointWrites + numRangeWrites - 1; i > 0; --i) {
int j = arbitrary.bounded(i + 1);
int j = arbitrary->bounded(i + 1);
if (i != j) {
using std::swap;
swap(writes[i], writes[j]);
@@ -704,7 +695,7 @@ struct TestDriver {
}
oldestVersion +=
arbitrary.bounded(10) ? arbitrary.bounded(10) : arbitrary.next();
arbitrary->bounded(10) ? arbitrary->bounded(10) : arbitrary->next();
oldestVersion = std::min(oldestVersion, writeVersion);
#ifdef THREAD_TEST
@@ -721,6 +712,20 @@ struct TestDriver {
ready.wait();
#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;
cs.addWrites(writes, numPointWrites + numRangeWrites, v);
CALLGRIND_STOP_INSTRUMENTATION;
@@ -729,6 +734,10 @@ struct TestDriver {
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);
if constexpr (kEnableAssertions) {
refImpl.setOldestVersion(oldestVersion);
@@ -739,24 +748,24 @@ struct TestDriver {
#endif
}
{
int numPointReads = arbitrary.bounded(100);
int numRangeReads = arbitrary.bounded(100);
int numPointReads = arbitrary->bounded(100);
int numRangeReads = arbitrary->bounded(100);
int64_t v = std::max<int64_t>(writeVersion - (arbitrary.bounded(10)
? arbitrary.bounded(10)
: arbitrary.next()),
int64_t v = std::max<int64_t>(writeVersion - (arbitrary->bounded(10)
? arbitrary->bounded(10)
: arbitrary->next()),
0);
auto *reads =
new (arena) ConflictSet::ReadRange[numPointReads + numRangeReads];
auto keys = set<std::string_view>(arena);
while (int(keys.size()) < numPointReads + numRangeReads * 2) {
if (!arbitrary.hasEntropy()) {
if (!arbitrary->hasEntropy()) {
return true;
}
int keyLen = prefixLen + arbitrary.bounded(kMaxKeySuffixLen);
int keyLen = prefixLen + arbitrary->bounded(kMaxKeySuffixLen);
auto *begin = new (arena) uint8_t[keyLen];
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));
}
@@ -765,7 +774,7 @@ struct TestDriver {
for (int pointsRemaining = numPointReads, rangesRemaining = numRangeReads;
pointsRemaining > 0 || rangesRemaining > 0; ++i) {
bool pointRead = pointsRemaining > 0 && rangesRemaining > 0
? bool(arbitrary.bounded(2))
? bool(arbitrary->bounded(2))
: pointsRemaining > 0;
if (pointRead) {
assert(pointsRemaining > 0);
@@ -787,10 +796,10 @@ struct TestDriver {
reads[i].readVersion = v;
#if DEBUG_VERBOSE && !defined(NDEBUG)
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);
} 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].end).c_str(), reads[i].readVersion);
}
@@ -839,24 +848,27 @@ struct TestDriver {
refImpl.check(reads, results2, numPointReads + numRangeReads);
}
auto compareResults = [reads](ConflictSet::Result *results1,
ConflictSet::Result *results2, int count) {
auto compareResults = [reads, this](ConflictSet::Result *results1,
ConflictSet::Result *results2,
int count) {
for (int i = 0; i < count; ++i) {
if (results1[i] != results2[i]) {
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(
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",
resultToStr(results2[i]), resultToStr(results1[i]),
printable(reads[i].begin).c_str(),
printable(reads[i].end).c_str(), reads[i].readVersion);
(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].end).c_str(), reads[i].readVersion);
}
return false;
}
-4
View File
@@ -778,10 +778,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
for (int s = stripes - 1; s >= 0; s--) {
for (int i = 0; i * 2 < ss; ++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 + 1] = w.second;
keyUpdates += 3;
+50 -17
View File
@@ -13,25 +13,58 @@ int main(int argc, char **argv) {
std::stringstream buffer;
buffer << t.rdbuf();
auto str = buffer.str();
TestDriver<ConflictSet, !PERF_TEST> driver{(const uint8_t *)str.data(),
str.size()};
while (!driver.next())
;
if (!driver.ok) {
abort();
Arbitrary arbitrary({(const uint8_t *)str.data(), str.size()});
TestDriver<ConflictSet, !PERF_TEST> driver1{arbitrary};
TestDriver<ConflictSet, !PERF_TEST> driver2{arbitrary};
bool done1 = false;
bool done2 = false;
for (;;) {
if (!done1) {
done1 = driver1.next();
if (!driver1.ok) {
abort();
}
}
if (!done2) {
done2 = driver2.next();
if (!driver2.ok) {
abort();
}
}
if (done1 && done2) {
break;
}
}
ConflictSet::MetricsV1 *metrics;
int metricsCount;
driver.cs.getMetricsV1(&metrics, &metricsCount);
printf("#################### METRICS 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());
{
ConflictSet::MetricsV1 *metrics;
int metricsCount;
driver1.cs.getMetricsV1(&metrics, &metricsCount);
printf("#################### METRICS for ConflictSet 1 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("");
}
{
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("");
}
puts("");
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
__aarch64_cas8_relax
__aarch64_ldadd8_relax
__getauxval@GLIBC_2.17
__stack_chk_fail@GLIBC_2.17
__stack_chk_guard@GLIBC_2.17
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.

Some files were not shown because too many files have changed in this diff Show More