55 Commits

Author SHA1 Message Date
b4b469a175 Use maxOfMax in fixupMaxVersion
Some checks failed
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 98.83% (1776/1797) * Branch Coverage: 64.91% (1506/2320) * Complexity Density: 0.00 * Lines of Code: 1797 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head There was a failure building this commit
2024-08-05 21:41:49 -07:00
0201e27498 Remove redundant setMaxVersion calls 2024-08-05 19:29:38 -07:00
2010920a2c Correct comment 2024-08-05 19:28:24 -07:00
19af8da65c Fix endNode's max version after the fact
This sets us up to unconditionally update the max version along the
search path for inserts, and avoid dispatching on type twice per
iteration.
2024-08-05 17:50:26 -07:00
80785e3c3b Avoid switch on parent type for max version during search 2024-08-05 16:40:58 -07:00
4580ee44b4 Add range reads to ServerBench
All checks were successful
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.60% (1739/1746) * Branch Coverage: 64.95% (1492/2297) * Complexity Density: 0.00 * Lines of Code: 1746 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-08-05 15:44:13 -07:00
2d3985ca40 Add a simple point read/write workload to ServerBench 2024-08-05 14:37:00 -07:00
c8be68db40 Add ServerBench.cpp 2024-08-05 12:20:38 -07:00
f5d021d6b6 Add multi-version rezero16
All checks were successful
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.60% (1739/1746) * Branch Coverage: 64.95% (1492/2297) * Complexity Density: 0.00 * Lines of Code: 1746 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-08-03 14:22:50 -07:00
1c41605b53 Use std::countr_zero instead of __builtin_ctz
Some checks reported errors
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
weaselab/conflict-set/pipeline/head Something is wrong with the build of this commit
Doesn't seem to affect codegen in these cases.
2024-08-03 10:01:12 -07:00
8f03a105bb Use target avx512f,avx512bw
All checks were successful
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.60% (1737/1744) * Branch Coverage: 64.99% (1498/2305) * Complexity Density: 0.00 * Lines of Code: 1744 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
Appears to fix gcc build
2024-08-02 21:47:23 -07:00
0e574856be Make checkMaxBetweenExclusive a multi-version function
This introduces more branches but reduces code size
2024-08-02 21:09:55 -07:00
493a6572ad Only exclude avx512-targeted functions from coverage
Some checks failed
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
weaselab/conflict-set/pipeline/head There was a failure building this commit
2024-08-02 20:53:30 -07:00
abce4591d0 Fix preprocessor guard for avx512 longestCommonPrefix 2024-08-02 20:46:32 -07:00
d1dc1247e1 Switch to new machine for benchmarks
Some checks failed
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
weaselab/conflict-set/pipeline/head There was a failure building this commit
2024-08-02 18:18:36 -07:00
f1ad68109a Skip lcp call in SearchStepWise if no partial key 2024-08-02 18:16:55 -07:00
c4443bc355 Remove len < 8 check in longestCommonPrefix
Micro benchmarks look a tiny bit better /shrug
2024-08-02 18:16:55 -07:00
857b402fe2 Add an avx512bw longestCommonPrefix 2024-08-02 18:16:55 -07:00
9b3e1b219b Remove small memmoves in erase 2024-08-02 18:16:55 -07:00
ab52c63935 Move local accum's into ReadContext 2024-08-02 18:16:55 -07:00
bad9d7ced8 Avoid some tls lookups for InternalVersionT::zero 2024-08-02 18:16:55 -07:00
c8d9dc034d Remove memmove call for inserting into Node16 2024-08-02 18:16:55 -07:00
72168ef6a3 Avoid memmove when inserting into Node3 2024-08-02 18:16:55 -07:00
620a0afd2a Add debug symbols and frame pointer
So that perf works out of the box. Leave it in the release artifacts/do
whatever cpack does by default for now.
2024-08-02 18:16:55 -07:00
b0414969be Update README.md
All checks were successful
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.60% (1741/1748) * Branch Coverage: 64.42% (1512/2347) * Complexity Density: 0.00 * Lines of Code: 1748 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
Benchmarks haven't been updated since adding metrics
2024-08-01 16:43:15 -07:00
1673e1c0dd Enforce 100% line coverage again. Closes #30
All checks were successful
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.60% (1741/1748) * Branch Coverage: 64.42% (1512/2347) * Complexity Density: 0.00 * Lines of Code: 1748 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-08-01 16:03:17 -07:00
7351b6e417 More gcovr exclusions for function multi-versioning
All checks were successful
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.60% (1741/1748) * Branch Coverage: 64.42% (1512/2347) * Complexity Density: 0.00 * Lines of Code: 1748 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-08-01 15:53:38 -07:00
561ed45e3e Show missing coverage lines in console output
All checks were successful
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.37% (1744/1755) * Branch Coverage: 64.31% (1512/2351) * Complexity Density: 0.00 * Lines of Code: 1755 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-08-01 15:43:09 -07:00
ca804f28c0 Get back to 100% line coverage locally
All checks were successful
Tests / Clang total: 1479, passed: 1479
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Debug total: 1477, passed: 1477
Tests / SIMD fallback total: 1479, passed: 1479
Tests / Release [gcc] total: 1479, passed: 1479
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 1102, passed: 1102
Tests / Coverage total: 1111, passed: 1111
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 99.37% (1744/1755) * Branch Coverage: 64.31% (1512/2351) * Complexity Density: 0.00 * Lines of Code: 1755 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-08-01 15:31:38 -07:00
3898cb596a Use _mm512_loadu_epi32 instead of memcpy
The latter somehow generated a vmovdqa64 instruction that segfaulted on
unaligned memory, with gcc and --coverage. Hmm.
2024-08-01 15:24:09 -07:00
b8edd92698 Fix warning 2024-08-01 15:23:43 -07:00
8e480528d5 Update corpus 2024-08-01 14:56:36 -07:00
4113183155 Attempt to fix likely arm bug
All checks were successful
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 |:-:|:-:|:-:|:-:|:-: |1|0|1|0|:zzz:
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.42% (1749/1777) * Branch Coverage: 64.06% (1515/2365) * Complexity Density: 0.00 * Lines of Code: 1777 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-08-01 14:01:41 -07:00
adb8fdc5e9 Simplify nextPhysical 2024-08-01 14:00:02 -07:00
c86e407985 Return Node from getChildGeq
It seems all callers ultimately want this
2024-08-01 13:53:18 -07:00
71a84057cb Find two more call sites for getFirstChildExists 2024-08-01 13:37:44 -07:00
9c5e5863c2 Simplify remaining "down left spine" loops 2024-08-01 13:17:33 -07:00
be67555756 Simplify more "down left spine" loops 2024-08-01 13:13:55 -07:00
988ec5ce69 Add getFirstChildExists 2024-08-01 13:05:40 -07:00
f5a0d81c52 Remove some redundant branches
I think they were getting optimized out, but still
2024-08-01 12:37:57 -07:00
3b2bd16cd1 Add overloads of getChild for each type 2024-08-01 11:42:55 -07:00
4b3df0a426 Avoid dispatching on node type twice in nextPhysical 2024-08-01 10:46:08 -07:00
4cdf6deb50 Remove a branch in happy path in addWrites 2024-08-01 10:28:50 -07:00
f21dde06d3 Group write metric accumulators into a struct 2024-07-31 21:45:20 -07:00
2b11650589 Update aarch64 import symbols
All checks were successful
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
fce998460f Use int64_t internally for metrics
Some checks failed
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
6da3125719 Remove everything wasm-related
All checks were successful
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
79410d071f Add accidentally-deleted corpus back
All checks were successful
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
1fcca6450d Fix point writes accounting
Previously it wouldn't count a singleton range write
2024-07-26 14:41:54 -07:00
55271ad06c Update corpus
All checks were successful
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
e675612599 Suppress some warnings in test code 2024-07-23 16:50:02 -07:00
42b5d50492 Update DEBUG_VERBOSE for interleaving conflict sets in test 2024-07-23 15:44:29 -07:00
6394995def Add a test where the "zero" bug causes an incorrect commit 2024-07-23 14:39:45 -07:00
c649bc7964 Interleave calls for two conflict sets in tests 2024-07-23 11:12:02 -07:00
ec85a06d01 Bump version
All checks were successful
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
757 changed files with 1174 additions and 759 deletions

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
@@ -37,8 +31,14 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
"MinSizeRel" "RelWithDebInfo")
endif()
add_compile_options(-fdata-sections -ffunction-sections -Wswitch-enum
-Werror=switch-enum -fPIC)
add_compile_options(
-fdata-sections
-ffunction-sections
-Wswitch-enum
-Werror=switch-enum
-fPIC
-g
-fno-omit-frame-pointer)
set(full_relro_flags "-pie;LINKER:-z,relro,-z,now,-z,noexecstack")
cmake_push_check_state()
@@ -81,15 +81,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 +153,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 +304,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)
@@ -358,6 +342,11 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
add_executable(driver_perf TestDriver.cpp)
target_compile_definitions(driver_perf PRIVATE PERF_TEST=1)
target_link_libraries(driver_perf PRIVATE ${PROJECT_NAME})
# server bench
add_executable(server_bench ServerBench.cpp)
target_link_libraries(server_bench PRIVATE ${PROJECT_NAME})
set_target_properties(server_bench PROPERTIES SKIP_BUILD_RPATH ON)
endif()
# packaging

File diff suppressed because it is too large Load Diff

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
Jenkinsfile vendored
View File

@@ -123,8 +123,8 @@ pipeline {
'''
recordCoverage qualityGates: [[criticality: 'NOTE', metric: 'MODULE']], tools: [[parser: 'COBERTURA', pattern: 'build/coverage.xml']]
sh '''
# Suppress again, because we haven't dealt with function multi-versioning for x86 yet
# gcovr -f ConflictSet.cpp --fail-under-line 100 > /dev/null
gcovr -f ConflictSet.cpp
gcovr -f ConflictSet.cpp --fail-under-line 100 > /dev/null
'''
}
}

104
README.md
View File

@@ -1,86 +1,38 @@
A data structure for optimistic concurrency control on ranges of bitwise-lexicographically-ordered keys.
Intended to replace FoundationDB's skip list.
Intended as an alternative to FoundationDB's skip list.
Hardware for all benchmarks is a mac m1 2020.
Hardware for all benchmarks is an AMD Ryzen 9 7900 with (2x32GB) 5600MT/s CL28-34-34-89 1.35V RAM
# FoundationDB's benchmark
# Microbenchmark
## Skip list
```
New conflict set: 1.957 sec
0.639 Mtransactions/sec
2.555 Mkeys/sec
Detect only: 1.845 sec
0.678 Mtransactions/sec
2.710 Mkeys/sec
Skiplist only: 1.263 sec
0.990 Mtransactions/sec
3.960 Mkeys/sec
Performance counters:
Build: 0.0546
Add: 0.0563
Detect: 1.84
D.Sort: 0.412
D.Combine: 0.0141
D.CheckRead: 0.671
D.CheckIntraBatch: 0.0068
D.MergeWrite: 0.592
D.RemoveBefore: 0.146
```
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 172.03 | 5,812,791.77 | 0.4% | 3,130.62 | 879.00 | 3.562 | 509.23 | 0.0% | 0.01 | `point reads`
| 167.44 | 5,972,130.71 | 0.2% | 3,065.14 | 862.27 | 3.555 | 494.30 | 0.0% | 0.01 | `prefix reads`
| 238.77 | 4,188,130.84 | 0.9% | 3,589.93 | 1,259.30 | 2.851 | 637.12 | 0.0% | 0.01 | `range reads`
| 424.01 | 2,358,426.70 | 0.2% | 5,620.05 | 2,242.35 | 2.506 | 854.80 | 1.7% | 0.01 | `point writes`
| 418.45 | 2,389,780.56 | 0.4% | 5,525.07 | 2,211.05 | 2.499 | 831.71 | 1.7% | 0.01 | `prefix writes`
| 254.87 | 3,923,568.88 | 2.6% | 3,187.01 | 1,366.50 | 2.332 | 529.11 | 2.7% | 0.02 | `range writes`
| 675.96 | 1,479,374.50 | 3.3% | 7,735.41 | 3,468.60 | 2.230 | 1,386.02 | 1.8% | 0.01 | `monotonic increasing point writes`
| 137,986.20 | 7,247.10 | 0.6% | 789,752.33 | 699,462.00 | 1.129 | 144,824.14 | 0.0% | 0.01 | `worst case for radix tree`
| 21.63 | 46,231,564.03 | 1.0% | 448.00 | 107.14 | 4.181 | 84.00 | 0.0% | 0.01 | `create and destroy`
## Radix tree (this implementation)
```
New conflict set: 1.366 sec
0.915 Mtransactions/sec
3.660 Mkeys/sec
Detect only: 1.248 sec
1.002 Mtransactions/sec
4.007 Mkeys/sec
Skiplist only: 0.573 sec
2.182 Mtransactions/sec
8.730 Mkeys/sec
Performance counters:
Build: 0.0594
Add: 0.0572
Detect: 1.25
D.Sort: 0.418
D.Combine: 0.0149
D.CheckRead: 0.232
D.CheckIntraBatch: 0.0067
D.MergeWrite: 0.341
D.RemoveBefore: 0.232
```
# Our benchmark
## Skip list
| ns/op | op/s | err% | total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
| 245.99 | 4,065,232.81 | 0.3% | 0.01 | `point reads`
| 265.93 | 3,760,430.49 | 0.2% | 0.01 | `prefix reads`
| 485.30 | 2,060,569.50 | 0.2% | 0.01 | `range reads`
| 449.60 | 2,224,195.17 | 0.4% | 0.01 | `point writes`
| 441.76 | 2,263,688.18 | 1.1% | 0.01 | `prefix writes`
| 245.42 | 4,074,647.54 | 2.4% | 0.02 | `range writes`
| 572.80 | 1,745,810.06 | 1.3% | 0.01 | `monotonic increasing point writes`
| 154,819.33 | 6,459.14 | 0.9% | 0.01 | `worst case for radix tree`
## Radix tree (this implementation)
| ns/op | op/s | err% | total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
| 19.17 | 52,163,930.66 | 0.1% | 0.01 | `point reads`
| 23.68 | 42,224,388.21 | 0.7% | 0.01 | `prefix reads`
| 63.30 | 15,797,506.06 | 0.9% | 0.01 | `range reads`
| 29.66 | 33,720,994.74 | 0.3% | 0.01 | `point writes`
| 43.50 | 22,987,781.25 | 1.0% | 0.01 | `prefix writes`
| 50.00 | 20,000,000.00 | 0.8% | 0.01 | `range writes`
| 103.25 | 9,684,786.47 | 2.9% | 0.01 | `monotonic increasing point writes`
| 1,181,500.00 | 846.38 | 2.3% | 0.01 | `worst case for radix tree`
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
| 17.03 | 58,732,967.93 | 0.6% | 276.28 | 87.96 | 3.141 | 52.15 | 0.4% | 0.01 | `point reads`
| 19.52 | 51,239,158.04 | 0.3% | 367.16 | 101.50 | 3.617 | 61.92 | 0.3% | 0.01 | `prefix reads`
| 47.74 | 20,947,676.63 | 0.5% | 998.16 | 247.43 | 4.034 | 161.64 | 0.2% | 0.01 | `range reads`
| 23.14 | 43,207,824.89 | 0.4% | 408.18 | 121.64 | 3.356 | 70.20 | 0.3% | 0.01 | `point writes`
| 38.02 | 26,302,115.66 | 0.1% | 709.72 | 199.70 | 3.554 | 134.26 | 0.3% | 0.01 | `prefix writes`
| 44.28 | 22,583,559.17 | 0.9% | 825.19 | 233.10 | 3.540 | 141.48 | 0.2% | 0.01 | `range writes`
| 85.50 | 11,695,990.63 | 0.5% | 1,488.16 | 455.68 | 3.266 | 289.22 | 0.1% | 0.01 | `monotonic increasing point writes`
| 338,388.50 | 2,955.18 | 3.3% | 4,097,087.00 | 1,809,996.00 | 2.264 | 759,645.00 | 0.0% | 0.01 | `worst case for radix tree`
| 84.84 | 11,787,313.59 | 1.4% | 1,716.02 | 440.50 | 3.896 | 271.00 | 0.0% | 0.01 | `create and destroy`
# "Real data" test
@@ -89,13 +41,13 @@ Point queries only, best of three runs. Gc ratio is the ratio of time spent doin
## skip list
```
Check: 11.3385 seconds, 329.718 MB/s, Add: 5.35612 seconds, 131.072 MB/s, Gc ratio: 45.7173%
Check: 4.47891 seconds, 364.05 MB/s, Add: 4.55599 seconds, 123.058 MB/s, Gc ratio: 37.1145%
```
## radix tree
```
Check: 2.48583 seconds, 1503.93 MB/s, Add: 2.12768 seconds, 329.954 MB/s, Gc ratio: 41.7943%
Check: 1.05813 seconds, 1540.97 MB/s, Add: 1.32071 seconds, 424.508 MB/s, Gc ratio: 42.2067%
```
## hash table
@@ -103,5 +55,5 @@ Check: 2.48583 seconds, 1503.93 MB/s, Add: 2.12768 seconds, 329.954 MB/s, Gc rat
(The hash table implementation doesn't work on range queries, and its purpose is to provide an idea of how fast point queries can be)
```
Check: 1.83386 seconds, 2038.6 MB/s, Add: 0.601411 seconds, 1167.32 MB/s, Gc ratio: 48.9776%
Check: 0.804094 seconds, 2027.81 MB/s, Add: 0.652952 seconds, 858.645 MB/s, Gc ratio: 35.3885%
```

233
ServerBench.cpp Normal file
View File

@@ -0,0 +1,233 @@
#include <atomic>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <string_view>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <thread>
#include <unistd.h>
#include "ConflictSet.h"
#include "third_party/nadeau.h"
std::atomic<int64_t> transactions;
constexpr int kBaseSearchDepth = 32;
constexpr int kWindowSize = 10000000;
std::basic_string<uint8_t> numToKey(int64_t num) {
std::basic_string<uint8_t> result;
result.resize(kBaseSearchDepth + sizeof(int64_t));
memset(result.data(), 0, kBaseSearchDepth);
int64_t be = __builtin_bswap64(num);
memcpy(result.data() + kBaseSearchDepth, &be, sizeof(int64_t));
return result;
}
void workload(weaselab::ConflictSet *cs) {
int64_t version = kWindowSize;
cs->addWrites(nullptr, 0, version);
for (;; transactions.fetch_add(1, std::memory_order_relaxed)) {
// Reads
{
auto beginK = numToKey(version - kWindowSize);
auto endK = numToKey(version - 1);
auto pointRv = version - kWindowSize + rand() % kWindowSize + 1;
auto pointK = numToKey(pointRv);
weaselab::ConflictSet::ReadRange reads[] = {
{
{pointK.data(), int(pointK.size())},
{nullptr, 0},
pointRv,
},
{
{beginK.data(), int(beginK.size())},
{endK.data(), int(endK.size())},
version - 2,
},
};
weaselab::ConflictSet::Result result[sizeof(reads) / sizeof(reads[0])];
cs->check(reads, result, sizeof(reads) / sizeof(reads[0]));
// for (int i = 0; i < sizeof(reads) / sizeof(reads[0]); ++i) {
// if (result[i] != weaselab::ConflictSet::Commit) {
// fprintf(stderr, "Unexpected conflict: [%s, %s) @ %" PRId64 "\n",
// printable(reads[i].begin).c_str(),
// printable(reads[i].end).c_str(), reads[i].readVersion);
// abort();
// }
// }
}
// Writes
{
weaselab::ConflictSet::WriteRange w;
auto k = numToKey(version);
w.begin.p = k.data();
w.end.len = 0;
if (version % (kWindowSize / 2) == 0) {
for (int l = 0; l <= k.size(); ++l) {
w.begin.len = l;
cs->addWrites(&w, 1, version);
}
} else {
w.begin.len = k.size();
cs->addWrites(&w, 1, version);
}
}
// GC
cs->setOldestVersion(version - kWindowSize);
++version;
}
}
// Adapted from getaddrinfo man page
int getListenFd(const char *node, const char *service) {
struct addrinfo hints;
struct addrinfo *result, *rp;
int sfd, s;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* stream socket */
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = nullptr;
hints.ai_addr = nullptr;
hints.ai_next = nullptr;
s = getaddrinfo(node, service, &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
abort();
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != nullptr; rp = rp->ai_next) {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1) {
continue;
}
int val = 1;
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) {
break; /* Success */
}
close(sfd);
}
freeaddrinfo(result); /* No longer needed */
if (rp == nullptr) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
abort();
}
int rv = listen(sfd, SOMAXCONN);
if (rv) {
perror("listen()");
abort();
}
return sfd;
}
// HTTP response
//
std::string_view part1 =
"HTTP/1.1 200 OK \r\nContent-type: text/plain; version=0.0.4; "
"charset=utf-8; escaping=values\r\nContent-Length: ";
// Decimal content length
std::string_view part2 = "\r\n\r\n";
// Body
double toSeconds(timeval t) {
return double(t.tv_sec) + double(t.tv_usec) * 1e-6;
}
int main(int argc, char **argv) {
if (argc != 3) {
goto fail;
}
{
int listenFd = getListenFd(argv[1], argv[2]);
weaselab::ConflictSet cs{0};
weaselab::ConflictSet::MetricsV1 *metrics;
int metricsCount;
cs.getMetricsV1(&metrics, &metricsCount);
auto w = std::thread{workload, &cs};
for (;;) {
struct sockaddr_storage peer_addr = {};
socklen_t peer_addr_len = sizeof(peer_addr);
const int connfd =
accept(listenFd, (struct sockaddr *)&peer_addr, &peer_addr_len);
std::string body;
rusage r;
getrusage(RUSAGE_SELF, &r);
body += "# HELP process_cpu_seconds_total Total user and system CPU time "
"spent in seconds.\n# TYPE process_cpu_seconds_total counter\n"
"process_cpu_seconds_total ";
body += std::to_string(toSeconds(r.ru_utime) + toSeconds(r.ru_stime));
body += "\n";
body += "# HELP process_resident_memory_bytes Resident memory size in "
"bytes.\n# TYPE process_resident_memory_bytes gauge\n"
"process_resident_memory_bytes ";
body += std::to_string(getCurrentRSS());
body += "\n";
body += "# HELP transactions_total Total number of transactions\n"
"# TYPE transactions_total counter\n"
"transactions_total ";
body += std::to_string(transactions.load(std::memory_order_relaxed));
body += "\n";
for (int i = 0; i < metricsCount; ++i) {
body += "# HELP ";
body += metrics[i].name;
body += " ";
body += metrics[i].help;
body += "\n";
body += "# TYPE ";
body += metrics[i].name;
body += " ";
body += metrics[i].type == metrics[i].Counter ? "counter" : "gauge";
body += "\n";
body += metrics[i].name;
body += " ";
body += std::to_string(metrics[i].getValue());
body += "\n";
}
auto len = std::to_string(body.size());
iovec iov[] = {
{(void *)part1.data(), part1.size()},
{(void *)len.data(), len.size()},
{(void *)part2.data(), part2.size()},
{(void *)body.data(), body.size()},
};
int written;
do {
written = writev(connfd, iov, sizeof(iov) / sizeof(iov[0]));
} while (written < 0 && errno == EINTR);
close(connfd);
}
}
fail:
fprintf(stderr, "Expected ./%s <host> <port>\n", argv[0]);
return 1;
}

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;

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("");
}
}

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.

View File

@@ -0,0 +1,5 @@
<EFBFBD><EFBFBD>
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.

View File

@@ -0,0 +1 @@
<EFBFBD>

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