Compare commits
136 Commits
5013c689a0
...
main
Author | SHA1 | Date | |
---|---|---|---|
2642d453dc | |||
7166811387 | |||
d68f208d9b | |||
81323972aa | |||
8694ba8b6a | |||
0cea5565b5 | |||
972f16ed8f | |||
2412684316 | |||
8190d2f24e | |||
8251631087 | |||
90fb2a9542 | |||
7c01f8ba0f | |||
0df2db7f8a | |||
5e975f3b2b | |||
bcbae026b2 | |||
e125b599b5 | |||
3f4d3b685a | |||
4198b8b090 | |||
8757d2387c | |||
4a22b95d53 | |||
03d6c7e471 | |||
ceecc62a63 | |||
80f0697e79 | |||
ce23d3995c | |||
6f899e063b | |||
e5b9c03e77 | |||
a158d375f5 | |||
ee5a84cd7b | |||
33f14e3d9b | |||
77262ee2d3 | |||
9945998e05 | |||
2777e016ff | |||
661ffcd843 | |||
3a34d3cecb | |||
189c73e3bd | |||
35987030fc | |||
0621741ec3 | |||
f5ec9f726a | |||
552fc11c5d | |||
71ace9cc55 | |||
bcf459304f | |||
f403c78410 | |||
08958d4109 | |||
dcc5275ec9 | |||
c5ef843f9e | |||
b78e817e24 | |||
9c82f17e20 | |||
665a9313a4 | |||
6e66202d5e | |||
a92271a205 | |||
0dbfb4deae | |||
6e229b6b36 | |||
2200de11c8 | |||
b37feb58dd | |||
94a4802824 | |||
707dbdb391 | |||
bdd343bb57 | |||
7b31bd5efe | |||
e255e1a926 | |||
f85b92f8db | |||
3c44614311 | |||
9c1ac3702e | |||
224d21648a | |||
33f9c89328 | |||
12c2d5eb95 | |||
db357e747d | |||
4494359ca2 | |||
f079d84bda | |||
724ec09248 | |||
4eaad39294 | |||
891100e649 | |||
22e55309be | |||
d6269c5b7c | |||
faacdff2d9 | |||
821179b8de | |||
681a961289 | |||
c73a3da14c | |||
5153d25cce | |||
d2ec4e7fae | |||
c7e2358746 | |||
ec1c1cf43f | |||
eaad0c69a7 | |||
309e6ab816 | |||
12b82c1be5 | |||
0cce9df8a8 | |||
0df09743da | |||
c4b0aa1085 | |||
051bfb05fe | |||
7e1bcbf9be | |||
4e685bbc3b | |||
b6bfc6f48d | |||
3b858551f3 | |||
2c1c26bc88 | |||
958ee15cfc | |||
9015b555de | |||
7aac73ee80 | |||
c06afeb81e | |||
b015711b7c | |||
f27ca6d6af | |||
c0bb175b7e | |||
6a6fe5738a | |||
dc16eccf06 | |||
3f15db7e82 | |||
e8a8b5aef1 | |||
b8fefff3ba | |||
2706b2f65e | |||
f1292efe41 | |||
a2d3d269ec | |||
8ff7a112b7 | |||
cf25b8626c | |||
e025f934d8 | |||
e5452c0f7d | |||
66fc526a55 | |||
21f08b9f88 | |||
10c2f06199 | |||
5cf04e9718 | |||
707b220fbc | |||
fd39065498 | |||
b963d481c9 | |||
e7ed47e288 | |||
04f138109b | |||
a0d07dd40c | |||
7fb408b466 | |||
6d265acfc7 | |||
67a61513b8 | |||
583f2e7612 | |||
66e5b033c0 | |||
1d705cd4b7 | |||
769cf8de9a | |||
84942a5bf8 | |||
7ad6872ee8 | |||
9db5eb960d | |||
5df25a138a | |||
381fbce0c0 | |||
87aeb349a3 | |||
28fb0d7faa |
39
Bench.cpp
39
Bench.cpp
@@ -17,26 +17,26 @@ constexpr int kPrefixLen = 0;
|
|||||||
|
|
||||||
constexpr int kMvccWindow = 100000;
|
constexpr int kMvccWindow = 100000;
|
||||||
|
|
||||||
std::span<const uint8_t> makeKey(Arena &arena, int index) {
|
TrivialSpan makeKey(Arena &arena, int index) {
|
||||||
|
|
||||||
auto result =
|
uint8_t *buf = new (arena) uint8_t[4 + kPrefixLen];
|
||||||
std::span<uint8_t>{new (arena) uint8_t[4 + kPrefixLen], 4 + kPrefixLen};
|
auto result = TrivialSpan{buf, 4 + kPrefixLen};
|
||||||
index = __builtin_bswap32(index);
|
index = __builtin_bswap32(index);
|
||||||
memset(result.data(), 0, kPrefixLen);
|
memset(buf, 0, kPrefixLen);
|
||||||
memcpy(result.data() + kPrefixLen, &index, 4);
|
memcpy(buf, &index, 4);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConflictSet::ReadRange singleton(Arena &arena, std::span<const uint8_t> key) {
|
ConflictSet::ReadRange singleton(Arena &arena, TrivialSpan key) {
|
||||||
auto r =
|
uint8_t *buf = new (arena) uint8_t[key.size() + 1];
|
||||||
std::span<uint8_t>(new (arena) uint8_t[key.size() + 1], key.size() + 1);
|
auto r = TrivialSpan(buf, key.size() + 1);
|
||||||
memcpy(r.data(), key.data(), key.size());
|
memcpy(buf, key.data(), key.size());
|
||||||
r[key.size()] = 0;
|
buf[key.size()] = 0;
|
||||||
return {{key.data(), int(key.size())}, {r.data(), int(r.size())}, 0};
|
return {{key.data(), int(key.size())}, {r.data(), int(r.size())}, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
ConflictSet::ReadRange prefixRange(Arena &arena, std::span<const uint8_t> key) {
|
ConflictSet::ReadRange prefixRange(Arena &arena, TrivialSpan key) {
|
||||||
int index;
|
int index;
|
||||||
for (index = key.size() - 1; index >= 0; index--)
|
for (index = key.size() - 1; index >= 0; index--)
|
||||||
if ((key[index]) != 255)
|
if ((key[index]) != 255)
|
||||||
@@ -48,14 +48,16 @@ ConflictSet::ReadRange prefixRange(Arena &arena, std::span<const uint8_t> key) {
|
|||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto r = std::span<uint8_t>(new (arena) uint8_t[index + 1], index + 1);
|
uint8_t *buf = new (arena) uint8_t[index + 1];
|
||||||
memcpy(r.data(), key.data(), index + 1);
|
auto r = TrivialSpan(buf, index + 1);
|
||||||
r[r.size() - 1]++;
|
memcpy(buf, key.data(), index + 1);
|
||||||
|
buf[r.size() - 1]++;
|
||||||
return {{key.data(), int(key.size())}, {r.data(), int(r.size())}, 0};
|
return {{key.data(), int(key.size())}, {r.data(), int(r.size())}, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
void benchConflictSet() {
|
void benchConflictSet() {
|
||||||
ankerl::nanobench::Bench bench;
|
ankerl::nanobench::Bench bench;
|
||||||
|
bench.minEpochIterations(10000);
|
||||||
ConflictSet cs{0};
|
ConflictSet cs{0};
|
||||||
|
|
||||||
bench.batch(kOpsPerTx);
|
bench.batch(kOpsPerTx);
|
||||||
@@ -81,14 +83,7 @@ void benchConflictSet() {
|
|||||||
++version;
|
++version;
|
||||||
}
|
}
|
||||||
|
|
||||||
// I don't know why std::less didn't work /shrug
|
auto points = set<TrivialSpan, std::less<>>(arena);
|
||||||
struct Less {
|
|
||||||
bool operator()(const std::span<const uint8_t> &lhs,
|
|
||||||
const std::span<const uint8_t> &rhs) const {
|
|
||||||
return lhs < rhs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
auto points = set<std::span<const uint8_t>, Less>(arena);
|
|
||||||
|
|
||||||
while (points.size() < kOpsPerTx * 2 + 1) {
|
while (points.size() < kOpsPerTx * 2 + 1) {
|
||||||
// TODO don't use rand?
|
// TODO don't use rand?
|
||||||
|
@@ -31,8 +31,30 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|||||||
"MinSizeRel" "RelWithDebInfo")
|
"MinSizeRel" "RelWithDebInfo")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_compile_options(-fdata-sections -ffunction-sections -Wswitch-enum
|
add_compile_options(
|
||||||
-Werror=switch-enum -fPIC)
|
-Werror=switch-enum
|
||||||
|
-Wswitch-enum
|
||||||
|
-Wunused-variable
|
||||||
|
-fPIC
|
||||||
|
-fdata-sections
|
||||||
|
-ffunction-sections
|
||||||
|
-fno-jump-tables # https://github.com/llvm/llvm-project/issues/54247
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
add_link_options("-Wno-unused-command-line-argument")
|
||||||
|
find_program(LLVM_OBJCOPY llvm-objcopy)
|
||||||
|
if(LLVM_OBJCOPY)
|
||||||
|
set(CMAKE_OBJCOPY
|
||||||
|
${LLVM_OBJCOPY}
|
||||||
|
CACHE FILEPATH "path to objcopy binary" FORCE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
add_compile_options("-Wno-maybe-uninitialized")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT APPLE)
|
if(NOT APPLE)
|
||||||
# This causes some versions of clang to crash on macos
|
# This causes some versions of clang to crash on macos
|
||||||
add_compile_options(-g -fno-omit-frame-pointer)
|
add_compile_options(-g -fno-omit-frame-pointer)
|
||||||
@@ -47,6 +69,22 @@ if(HAS_FULL_RELRO)
|
|||||||
endif()
|
endif()
|
||||||
cmake_pop_check_state()
|
cmake_pop_check_state()
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL
|
||||||
|
arm64)
|
||||||
|
add_compile_options(-mbranch-protection=standard)
|
||||||
|
else()
|
||||||
|
add_compile_options(-fcf-protection)
|
||||||
|
set(rewrite_endbr_flags "-fuse-ld=mold;LINKER:-z,rewrite-endbr")
|
||||||
|
cmake_push_check_state()
|
||||||
|
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${rewrite_endbr_flags})
|
||||||
|
check_cxx_source_compiles("int main(){}" HAS_REWRITE_ENDBR FAIL_REGEX
|
||||||
|
"warning:")
|
||||||
|
if(HAS_REWRITE_ENDBR)
|
||||||
|
add_link_options(${rewrite_endbr_flags})
|
||||||
|
endif()
|
||||||
|
cmake_pop_check_state()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(version_script_flags
|
set(version_script_flags
|
||||||
LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.map)
|
LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.map)
|
||||||
cmake_push_check_state()
|
cmake_push_check_state()
|
||||||
@@ -64,27 +102,17 @@ option(DISABLE_TSAN "Disable TSAN" OFF)
|
|||||||
# https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq
|
# https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq
|
||||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/valgrind)
|
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/valgrind)
|
||||||
|
|
||||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Wno-invalid-offsetof>)
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
add_link_options(-Wl,-dead_strip)
|
add_link_options(-Wl,-dead_strip)
|
||||||
else()
|
else()
|
||||||
add_link_options(-Wl,--gc-sections)
|
add_link_options(-Wl,--gc-sections)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT USE_SIMD_FALLBACK)
|
if(USE_SIMD_FALLBACK)
|
||||||
cmake_push_check_state()
|
add_compile_definitions(USE_SIMD_FALLBACK)
|
||||||
list(APPEND CMAKE_REQUIRED_FLAGS -mavx)
|
else()
|
||||||
check_include_file_cxx("immintrin.h" HAS_AVX)
|
if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64)
|
||||||
if(HAS_AVX)
|
|
||||||
add_compile_options(-mavx)
|
add_compile_options(-mavx)
|
||||||
add_compile_definitions(HAS_AVX)
|
|
||||||
endif()
|
|
||||||
cmake_pop_check_state()
|
|
||||||
|
|
||||||
check_include_file_cxx("arm_neon.h" HAS_ARM_NEON)
|
|
||||||
if(HAS_ARM_NEON)
|
|
||||||
add_compile_definitions(HAS_ARM_NEON)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -347,6 +375,15 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
|
|||||||
${symbol_imports})
|
${symbol_imports})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_CROSSCOMPILING)
|
||||||
|
find_program(HARDENING_CHECK hardening-check)
|
||||||
|
if(HARDENING_CHECK)
|
||||||
|
add_test(NAME hardening_check
|
||||||
|
COMMAND ${HARDENING_CHECK} $<TARGET_FILE:${PROJECT_NAME}>
|
||||||
|
--nofortify --nostackprotector)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# bench
|
# bench
|
||||||
add_executable(conflict_set_bench Bench.cpp)
|
add_executable(conflict_set_bench Bench.cpp)
|
||||||
target_link_libraries(conflict_set_bench PRIVATE ${PROJECT_NAME} nanobench)
|
target_link_libraries(conflict_set_bench PRIVATE ${PROJECT_NAME} nanobench)
|
||||||
|
2933
ConflictSet.cpp
2933
ConflictSet.cpp
File diff suppressed because it is too large
Load Diff
16
Dockerfile
16
Dockerfile
@@ -11,23 +11,24 @@ RUN TZ=America/Los_Angeles DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
|||||||
binutils-aarch64-linux-gnu \
|
binutils-aarch64-linux-gnu \
|
||||||
build-essential \
|
build-essential \
|
||||||
ccache \
|
ccache \
|
||||||
clang \
|
|
||||||
cmake \
|
cmake \
|
||||||
curl \
|
curl \
|
||||||
doxygen \
|
devscripts \
|
||||||
file \
|
|
||||||
g++-aarch64-linux-gnu \
|
g++-aarch64-linux-gnu \
|
||||||
gcovr \
|
gcovr \
|
||||||
git \
|
git \
|
||||||
gperf \
|
gnupg \
|
||||||
graphviz \
|
|
||||||
libc6-dbg \
|
libc6-dbg \
|
||||||
|
lsb-release \
|
||||||
|
mold \
|
||||||
ninja-build \
|
ninja-build \
|
||||||
pre-commit \
|
pre-commit \
|
||||||
python3-requests \
|
python3-requests \
|
||||||
qemu-user \
|
qemu-user \
|
||||||
rpm \
|
rpm \
|
||||||
|
software-properties-common \
|
||||||
texlive-full \
|
texlive-full \
|
||||||
|
wget \
|
||||||
zstd
|
zstd
|
||||||
|
|
||||||
# Install recent valgrind from source
|
# Install recent valgrind from source
|
||||||
@@ -43,6 +44,11 @@ RUN curl -Ls https://sourceware.org/pub/valgrind/valgrind-3.22.0.tar.bz2 -o valg
|
|||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf /tmp/*
|
rm -rf /tmp/*
|
||||||
|
|
||||||
|
# Recent clang
|
||||||
|
RUN wget https://apt.llvm.org/llvm.sh && chmod +x ./llvm.sh && ./llvm.sh 20
|
||||||
|
|
||||||
|
RUN apt-get -y install clang llvm
|
||||||
|
|
||||||
# Set after building valgrind, which doesn't build with clang for some reason
|
# Set after building valgrind, which doesn't build with clang for some reason
|
||||||
ENV CC=clang
|
ENV CC=clang
|
||||||
ENV CXX=clang++
|
ENV CXX=clang++
|
||||||
|
76
Internal.h
76
Internal.h
@@ -18,7 +18,6 @@ using namespace weaselab;
|
|||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_set>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <callgrind.h>
|
#include <callgrind.h>
|
||||||
@@ -26,9 +25,38 @@ using namespace weaselab;
|
|||||||
#define DEBUG_VERBOSE 0
|
#define DEBUG_VERBOSE 0
|
||||||
#define SHOW_MEMORY 0
|
#define SHOW_MEMORY 0
|
||||||
|
|
||||||
[[nodiscard]] inline auto
|
// std::span is not trivially constructible. We want a span that leaves its
|
||||||
operator<=>(const std::span<const uint8_t> &lhs,
|
// members uninitialized for performance reasons.
|
||||||
const std::span<const uint8_t> &rhs) noexcept {
|
struct TrivialSpan {
|
||||||
|
TrivialSpan() = default;
|
||||||
|
TrivialSpan(const uint8_t *begin, int len) : begin(begin), len(len) {}
|
||||||
|
|
||||||
|
uint8_t back() const {
|
||||||
|
assert(len > 0);
|
||||||
|
return begin[len - 1];
|
||||||
|
}
|
||||||
|
uint8_t front() const {
|
||||||
|
assert(len > 0);
|
||||||
|
return begin[0];
|
||||||
|
}
|
||||||
|
uint8_t operator[](int i) const {
|
||||||
|
assert(0 <= i);
|
||||||
|
assert(i < len);
|
||||||
|
return begin[i];
|
||||||
|
}
|
||||||
|
int size() const { return len; }
|
||||||
|
TrivialSpan subspan(int offset, int len) { return {begin + offset, len}; }
|
||||||
|
const uint8_t *data() const { return begin; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint8_t *begin;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::is_trivial_v<TrivialSpan>);
|
||||||
|
|
||||||
|
[[nodiscard]] inline auto operator<=>(const TrivialSpan &lhs,
|
||||||
|
const TrivialSpan &rhs) noexcept {
|
||||||
int cl = std::min<int>(lhs.size(), rhs.size());
|
int cl = std::min<int>(lhs.size(), rhs.size());
|
||||||
if (cl > 0) {
|
if (cl > 0) {
|
||||||
if (auto c = memcmp(lhs.data(), rhs.data(), cl) <=> 0; c != 0) {
|
if (auto c = memcmp(lhs.data(), rhs.data(), cl) <=> 0; c != 0) {
|
||||||
@@ -38,7 +66,7 @@ operator<=>(const std::span<const uint8_t> &lhs,
|
|||||||
return lhs.size() <=> rhs.size();
|
return lhs.size() <=> rhs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline auto operator<=>(const std::span<const uint8_t> &lhs,
|
[[nodiscard]] inline auto operator<=>(const TrivialSpan &lhs,
|
||||||
const ConflictSet::Key &rhs) noexcept {
|
const ConflictSet::Key &rhs) noexcept {
|
||||||
int cl = std::min<int>(lhs.size(), rhs.len);
|
int cl = std::min<int>(lhs.size(), rhs.len);
|
||||||
if (cl > 0) {
|
if (cl > 0) {
|
||||||
@@ -46,7 +74,18 @@ operator<=>(const std::span<const uint8_t> &lhs,
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lhs.size() <=> size_t(rhs.len);
|
return lhs.size() <=> rhs.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline auto operator<=>(const ConflictSet::Key &lhs,
|
||||||
|
const ConflictSet::Key &rhs) noexcept {
|
||||||
|
int cl = std::min<int>(lhs.len, rhs.len);
|
||||||
|
if (cl > 0) {
|
||||||
|
if (auto c = memcmp(lhs.p, rhs.p, cl) <=> 0; c != 0) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lhs.len <=> rhs.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This header contains code that we want to reuse outside of ConflictSet.cpp or
|
// This header contains code that we want to reuse outside of ConflictSet.cpp or
|
||||||
@@ -328,23 +367,6 @@ template <class T, class C = std::less<T>> auto set(Arena &arena) {
|
|||||||
return Set<T, C>(ArenaAlloc<T>(&arena));
|
return Set<T, C>(ArenaAlloc<T>(&arena));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> struct MyHash;
|
|
||||||
|
|
||||||
template <class T> struct MyHash<T *> {
|
|
||||||
size_t operator()(const T *t) const noexcept {
|
|
||||||
size_t result;
|
|
||||||
memcpy(&result, &t, sizeof(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
using HashSet =
|
|
||||||
std::unordered_set<T, MyHash<T>, std::equal_to<T>, ArenaAlloc<T>>;
|
|
||||||
template <class T> auto hashSet(Arena &arena) {
|
|
||||||
return HashSet<T>(ArenaAlloc<T>(&arena));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
bool operator==(const ArenaAlloc<T> &lhs, const ArenaAlloc<U> &rhs) {
|
bool operator==(const ArenaAlloc<T> &lhs, const ArenaAlloc<U> &rhs) {
|
||||||
return lhs.arena == rhs.arena;
|
return lhs.arena == rhs.arena;
|
||||||
@@ -569,7 +591,7 @@ inline std::string printable(const Key &key) {
|
|||||||
return printable(std::string_view((const char *)key.p, key.len));
|
return printable(std::string_view((const char *)key.p, key.len));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string printable(std::span<const uint8_t> key) {
|
inline std::string printable(TrivialSpan key) {
|
||||||
return printable(std::string_view((const char *)key.data(), key.size()));
|
return printable(std::string_view((const char *)key.data(), key.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,10 +699,8 @@ struct TestDriver {
|
|||||||
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 = TrivialSpan(writes[i].begin.p, writes[i].begin.len) <=>
|
||||||
std::span<const uint8_t>(writes[i].begin.p,
|
TrivialSpan(writes[i].end.p, writes[i].end.len);
|
||||||
writes[i].begin.len) <=>
|
|
||||||
std::span<const uint8_t>(writes[i].end.p, writes[i].end.len);
|
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(writes[i].begin, writes[i].end);
|
swap(writes[i].begin, writes[i].end);
|
||||||
|
46
Jenkinsfile
vendored
46
Jenkinsfile
vendored
@@ -11,11 +11,11 @@ def CleanBuildAndTest(String cmakeArgs) {
|
|||||||
catchError {
|
catchError {
|
||||||
sh '''
|
sh '''
|
||||||
cd build
|
cd build
|
||||||
ctest --no-compress-output --test-output-size-passed 100000 --test-output-size-failed 100000 -T Test -j `nproc` --timeout 90
|
ctest --no-compress-output --test-output-size-passed 100000 --test-output-size-failed 100000 -T Test -j `nproc` --timeout 90 > /dev/null
|
||||||
zstd Testing/*/Test.xml
|
zstd Testing/*/Test.xml
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
xunit tools: [CTest(pattern: 'build/Testing/*/Test.xml')], reduceLog: false, skipPublishingChecks: false
|
xunit tools: [CTest(pattern: 'build/Testing/*/Test.xml')], skipPublishingChecks: false
|
||||||
minio bucket: 'jenkins', credentialsId: 'jenkins-minio', excludes: '', host: 'minio.weaselab.dev', includes: 'build/Testing/*/Test.xml.zst', targetFolder: '${JOB_NAME}/${BUILD_NUMBER}/${STAGE_NAME}/'
|
minio bucket: 'jenkins', credentialsId: 'jenkins-minio', excludes: '', host: 'minio.weaselab.dev', includes: 'build/Testing/*/Test.xml.zst', targetFolder: '${JOB_NAME}/${BUILD_NUMBER}/${STAGE_NAME}/'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,18 +36,6 @@ pipeline {
|
|||||||
sh 'pre-commit run --all-files --show-diff-on-failure'
|
sh 'pre-commit run --all-files --show-diff-on-failure'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Clang') {
|
|
||||||
agent {
|
|
||||||
dockerfile {
|
|
||||||
args '-v /home/jenkins/ccache:/ccache'
|
|
||||||
reuseNode true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
CleanBuildAndTest("")
|
|
||||||
recordIssues(tools: [clang()])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('64 bit versions') {
|
stage('64 bit versions') {
|
||||||
agent {
|
agent {
|
||||||
dockerfile {
|
dockerfile {
|
||||||
@@ -81,7 +69,7 @@ pipeline {
|
|||||||
CleanBuildAndTest("-DUSE_SIMD_FALLBACK=ON")
|
CleanBuildAndTest("-DUSE_SIMD_FALLBACK=ON")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Release [gcc]') {
|
stage('Release [clang]') {
|
||||||
agent {
|
agent {
|
||||||
dockerfile {
|
dockerfile {
|
||||||
args '-v /home/jenkins/ccache:/ccache'
|
args '-v /home/jenkins/ccache:/ccache'
|
||||||
@@ -89,8 +77,8 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
CleanBuildAndTest("-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS=-DNVALGRIND")
|
CleanBuildAndTest("-DCMAKE_CXX_FLAGS=-DNVALGRIND")
|
||||||
recordIssues(tools: [gcc()])
|
recordIssues(tools: [clang()])
|
||||||
sh '''
|
sh '''
|
||||||
cd build
|
cd build
|
||||||
cpack -G DEB
|
cpack -G DEB
|
||||||
@@ -103,7 +91,19 @@ pipeline {
|
|||||||
minio bucket: 'jenkins', credentialsId: 'jenkins-minio', excludes: '', host: 'minio.weaselab.dev', includes: 'build/*.deb,build/*.rpm,paper/*.pdf', targetFolder: '${JOB_NAME}/${BUILD_NUMBER}/${STAGE_NAME}/'
|
minio bucket: 'jenkins', credentialsId: 'jenkins-minio', excludes: '', host: 'minio.weaselab.dev', includes: 'build/*.deb,build/*.rpm,paper/*.pdf', targetFolder: '${JOB_NAME}/${BUILD_NUMBER}/${STAGE_NAME}/'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Release [gcc,aarch64]') {
|
stage('gcc') {
|
||||||
|
agent {
|
||||||
|
dockerfile {
|
||||||
|
args '-v /home/jenkins/ccache:/ccache'
|
||||||
|
reuseNode true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
CleanBuildAndTest("-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++")
|
||||||
|
recordIssues(tools: [gcc()])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Release [clang,aarch64]') {
|
||||||
agent {
|
agent {
|
||||||
dockerfile {
|
dockerfile {
|
||||||
args '-v /home/jenkins/ccache:/ccache'
|
args '-v /home/jenkins/ccache:/ccache'
|
||||||
@@ -129,16 +129,16 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
filter_args = "-f ConflictSet.cpp -f LongestCommonPrefix.h -f Metrics.h"
|
gcov_args = "-f ConflictSet.cpp -f LongestCommonPrefix.h -f Metrics.h --gcov-executable 'llvm-cov gcov' --exclude-noncode-lines"
|
||||||
}
|
}
|
||||||
CleanBuildAndTest("-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_FLAGS=--coverage -DCMAKE_CXX_FLAGS=--coverage -DCMAKE_BUILD_TYPE=Debug -DDISABLE_TSAN=ON")
|
CleanBuildAndTest("-DCMAKE_C_FLAGS=--coverage -DCMAKE_CXX_FLAGS=--coverage -DCMAKE_BUILD_TYPE=Debug -DDISABLE_TSAN=ON")
|
||||||
sh """
|
sh """
|
||||||
gcovr ${filter_args} --cobertura > build/coverage.xml
|
gcovr ${gcov_args} --cobertura > build/coverage.xml
|
||||||
"""
|
"""
|
||||||
recordCoverage qualityGates: [[criticality: 'NOTE', metric: 'MODULE']], tools: [[parser: 'COBERTURA', pattern: 'build/coverage.xml']]
|
recordCoverage qualityGates: [[criticality: 'NOTE', metric: 'MODULE']], tools: [[parser: 'COBERTURA', pattern: 'build/coverage.xml']]
|
||||||
sh """
|
sh """
|
||||||
gcovr ${filter_args}
|
gcovr ${gcov_args}
|
||||||
gcovr ${filter_args} --fail-under-line 100 > /dev/null
|
gcovr ${gcov_args} --fail-under-line 100 > /dev/null
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -129,7 +129,7 @@ longestCommonPrefix(const uint8_t *ap, const uint8_t *bp, int cl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int end;
|
int end; // GCOVR_EXCL_LINE
|
||||||
|
|
||||||
// kStride * kUnrollCount at a time
|
// kStride * kUnrollCount at a time
|
||||||
end = cl & ~(kStride * kUnrollFactor - 1);
|
end = cl & ~(kStride * kUnrollFactor - 1);
|
||||||
|
57
README.md
57
README.md
@@ -2,7 +2,16 @@ A data structure for optimistic concurrency control on ranges of bitwise-lexicog
|
|||||||
|
|
||||||
Intended as an alternative to FoundationDB's skip list.
|
Intended as an alternative to FoundationDB's skip list.
|
||||||
|
|
||||||
Hardware for all benchmarks is an AMD Ryzen 9 7900 with (2x32GB) 5600MT/s CL28-34-34-89 1.35V RAM
|
Hardware for all benchmarks is an AMD Ryzen 9 7900 with (2x32GB) 5600MT/s CL28-34-34-89 1.35V RAM.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ clang++ --version
|
||||||
|
|
||||||
|
Ubuntu clang version 20.0.0 (++20241120082228+86734c857724-1~exp1~20241120202359.554)
|
||||||
|
Target: x86_64-pc-linux-gnu
|
||||||
|
Thread model: posix
|
||||||
|
InstalledDir: /usr/lib/llvm-20/bin
|
||||||
|
```
|
||||||
|
|
||||||
# Microbenchmark
|
# Microbenchmark
|
||||||
|
|
||||||
@@ -10,44 +19,45 @@ Hardware for all benchmarks is an AMD Ryzen 9 7900 with (2x32GB) 5600MT/s CL28-3
|
|||||||
|
|
||||||
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|
| 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`
|
| 161.29 | 6,200,056.17 | 0.1% | 3,014.03 | 831.04 | 3.627 | 504.59 | 0.0% | 1.93 | `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`
|
| 158.32 | 6,316,160.64 | 0.1% | 2,954.16 | 815.80 | 3.621 | 490.17 | 0.0% | 1.89 | `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`
|
| 237.39 | 4,212,409.50 | 0.2% | 3,592.41 | 1,233.96 | 2.911 | 629.31 | 0.0% | 2.84 | `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`
|
| 442.11 | 2,261,878.94 | 0.0% | 4,450.57 | 2,314.25 | 1.923 | 707.92 | 2.1% | 5.28 | `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`
|
| 439.89 | 2,273,308.53 | 0.1% | 4,410.22 | 2,302.29 | 1.916 | 694.74 | 2.1% | 5.25 | `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`
|
| 290.96 | 3,436,936.78 | 0.0% | 2,315.38 | 1,528.68 | 1.515 | 396.69 | 3.3% | 3.49 | `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`
|
| 476.93 | 2,096,762.02 | 0.6% | 6,999.33 | 2,484.94 | 2.817 | 1,251.73 | 1.3% | 0.06 | `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`
|
| 131,736.57 | 7,590.91 | 1.1% | 807,444.50 | 704,941.71 | 1.145 | 144,584.60 | 0.9% | 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`
|
| 45.50 | 21,978,369.95 | 1.1% | 902.00 | 232.36 | 3.882 | 132.00 | 0.0% | 0.01 | `create and destroy`
|
||||||
|
|
||||||
## Radix tree (this implementation)
|
## Radix tree (this implementation)
|
||||||
|
|
||||||
|
|
||||||
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|
| ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark
|
||||||
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|
||||||
| 12.88 | 77,653,350.77 | 0.5% | 185.37 | 64.45 | 2.876 | 41.51 | 0.4% | 0.01 | `point reads`
|
| 12.36 | 80,885,626.43 | 0.2% | 243.56 | 63.62 | 3.828 | 31.07 | 0.6% | 0.15 | `point reads`
|
||||||
| 14.67 | 68,179,354.49 | 0.1% | 271.44 | 73.40 | 3.698 | 53.70 | 0.3% | 0.01 | `prefix reads`
|
| 14.18 | 70,502,196.81 | 0.1% | 297.72 | 73.13 | 4.071 | 40.31 | 0.5% | 0.17 | `prefix reads`
|
||||||
| 34.84 | 28,701,444.36 | 0.3% | 715.74 | 175.27 | 4.084 | 127.30 | 0.2% | 0.01 | `range reads`
|
| 33.44 | 29,901,623.04 | 0.1% | 767.90 | 172.42 | 4.454 | 101.32 | 0.2% | 0.40 | `range reads`
|
||||||
| 17.12 | 58,422,988.28 | 0.2% | 314.30 | 86.11 | 3.650 | 39.82 | 0.4% | 0.01 | `point writes`
|
| 19.48 | 51,342,564.70 | 0.3% | 374.45 | 100.43 | 3.728 | 48.92 | 0.5% | 0.23 | `point writes`
|
||||||
| 31.42 | 31,830,804.65 | 0.1% | 591.06 | 158.07 | 3.739 | 82.67 | 0.2% | 0.01 | `prefix writes`
|
| 37.46 | 26,694,471.44 | 0.1% | 672.00 | 193.14 | 3.479 | 101.28 | 0.3% | 0.45 | `prefix writes`
|
||||||
| 37.37 | 26,759,432.70 | 2.2% | 681.98 | 188.95 | 3.609 | 96.10 | 0.1% | 0.01 | `range writes`
|
| 38.78 | 25,784,784.34 | 0.0% | 738.26 | 199.93 | 3.693 | 111.59 | 0.1% | 0.47 | `range writes`
|
||||||
| 76.72 | 13,035,140.63 | 2.3% | 1,421.28 | 387.17 | 3.671 | 257.76 | 0.1% | 0.01 | `monotonic increasing point writes`
|
| 76.05 | 13,148,995.74 | 0.7% | 1,450.77 | 397.16 | 3.653 | 275.72 | 0.0% | 0.01 | `monotonic increasing point writes`
|
||||||
| 297,452.00 | 3,361.89 | 0.9% | 3,508,083.00 | 1,500,834.67 | 2.337 | 727,525.33 | 0.1% | 0.01 | `worst case for radix tree`
|
| 286,920.33 | 3,485.29 | 0.4% | 4,117,948.00 | 1,521,352.00 | 2.707 | 714,833.00 | 0.1% | 0.01 | `worst case for radix tree`
|
||||||
| 87.70 | 11,402,490.60 | 1.0% | 1,795.00 | 442.09 | 4.060 | 297.00 | 0.0% | 0.01 | `create and destroy`
|
| 95.66 | 10,453,798.72 | 0.5% | 1,986.00 | 495.04 | 4.012 | 315.00 | 0.0% | 0.01 | `create and destroy`
|
||||||
|
|
||||||
# "Real data" test
|
# "Real data" test
|
||||||
|
|
||||||
Point queries only, best of three runs. Gc ratio is the ratio of time spent doing garbage collection to time spent adding writes or doing garbage collection. Lower is better.
|
Point queries only. Gc ratio is the ratio of time spent doing garbage collection to time spent adding writes or doing garbage collection. Lower is better.
|
||||||
|
|
||||||
## skip list
|
## skip list
|
||||||
|
|
||||||
```
|
```
|
||||||
Check: 4.47891 seconds, 364.05 MB/s, Add: 4.55599 seconds, 123.058 MB/s, Gc ratio: 37.1145%
|
Check: 4.53508 seconds, 371.81 MB/s, Add: 3.81222 seconds, 150.919 MB/s, Gc ratio: 33.66%, Peak idle memory: 5.61007e+06
|
||||||
```
|
```
|
||||||
|
|
||||||
## radix tree
|
## radix tree
|
||||||
|
|
||||||
```
|
```
|
||||||
Check: 0.953012 seconds, 1710.94 MB/s, Add: 1.30025 seconds, 431.188 MB/s, Gc ratio: 43.9816%, Peak idle memory: 2.28375e+06
|
Check: 0.957735 seconds, 1760.6 MB/s, Add: 1.19942 seconds, 479.678 MB/s, Gc ratio: 38.6069%, Peak idle memory: 2.05667e+06
|
||||||
```
|
```
|
||||||
|
|
||||||
## hash table
|
## hash table
|
||||||
@@ -55,5 +65,6 @@ Check: 0.953012 seconds, 1710.94 MB/s, Add: 1.30025 seconds, 431.188 MB/s, Gc ra
|
|||||||
(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)
|
(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: 0.804094 seconds, 2027.81 MB/s, Add: 0.652952 seconds, 858.645 MB/s, Gc ratio: 35.3885%
|
Check: 0.804598 seconds, 2095.69 MB/s, Add: 0.671221 seconds, 857.147 MB/s, Gc ratio: 35.0034%, Peak idle memory: 0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string_view>
|
#include <span>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -64,7 +64,7 @@ int main(int argc, const char **argv) {
|
|||||||
auto *const mapOriginal = begin;
|
auto *const mapOriginal = begin;
|
||||||
const auto sizeOriginal = size;
|
const auto sizeOriginal = size;
|
||||||
|
|
||||||
using StringView = std::basic_string_view<uint8_t>;
|
using StringView = std::span<const uint8_t>;
|
||||||
|
|
||||||
StringView write;
|
StringView write;
|
||||||
std::vector<StringView> reads;
|
std::vector<StringView> reads;
|
||||||
@@ -78,9 +78,9 @@ int main(int argc, const char **argv) {
|
|||||||
end = (uint8_t *)memchr(begin, '\n', size);
|
end = (uint8_t *)memchr(begin, '\n', size);
|
||||||
|
|
||||||
if (line.size() > 0 && line[0] == 'P') {
|
if (line.size() > 0 && line[0] == 'P') {
|
||||||
write = line.substr(2, line.size());
|
write = line.subspan(2, line.size());
|
||||||
} else if (line.size() > 0 && line[0] == 'L') {
|
} else if (line.size() > 0 && line[0] == 'L') {
|
||||||
reads.push_back(line.substr(2, line.size()));
|
reads.push_back(line.subspan(2, line.size()));
|
||||||
} else if (line.empty()) {
|
} else if (line.empty()) {
|
||||||
{
|
{
|
||||||
readRanges.resize(reads.size());
|
readRanges.resize(reads.size());
|
||||||
@@ -133,10 +133,10 @@ int main(int argc, const char **argv) {
|
|||||||
int metricsCount;
|
int metricsCount;
|
||||||
cs.getMetricsV1(&metrics, &metricsCount);
|
cs.getMetricsV1(&metrics, &metricsCount);
|
||||||
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);
|
fprintf(stderr, "# HELP %s %s\n", metrics[i].name, metrics[i].help);
|
||||||
printf("# TYPE %s %s\n", metrics[i].name,
|
fprintf(stderr, "# TYPE %s %s\n", metrics[i].name,
|
||||||
metrics[i].type == metrics[i].Counter ? "counter" : "gauge");
|
metrics[i].type == metrics[i].Counter ? "counter" : "gauge");
|
||||||
printf("%s %g\n", metrics[i].name, metrics[i].getValue());
|
fprintf(stderr, "%s %g\n", metrics[i].name, metrics[i].getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Check: %g seconds, %g MB/s, Add: %g seconds, %g MB/s, Gc ratio: "
|
printf("Check: %g seconds, %g MB/s, Add: %g seconds, %g MB/s, Gc ratio: "
|
||||||
|
254
ServerBench.cpp
254
ServerBench.cpp
@@ -1,5 +1,7 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -18,62 +20,210 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "ConflictSet.h"
|
#include "ConflictSet.h"
|
||||||
|
#include "Internal.h"
|
||||||
#include "third_party/nadeau.h"
|
#include "third_party/nadeau.h"
|
||||||
|
|
||||||
|
constexpr int kCacheLine = 64; // TODO mac m1 is 128
|
||||||
|
|
||||||
|
template <class T> struct TxQueue {
|
||||||
|
|
||||||
|
explicit TxQueue(int lgSlotCount)
|
||||||
|
: slotCount(1 << lgSlotCount), slotCountMask(slotCount - 1),
|
||||||
|
slots(new T[slotCount]) {
|
||||||
|
// Otherwise we can't tell the difference between full and empty.
|
||||||
|
assert(!(slotCountMask & 0x80000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call from producer thread, after ensuring consumer is no longer accessing
|
||||||
|
/// it somehow
|
||||||
|
~TxQueue() { delete[] slots; }
|
||||||
|
|
||||||
|
/// Must be called from the producer thread
|
||||||
|
void push(T t) {
|
||||||
|
if (wouldBlock()) {
|
||||||
|
// Wait for pops to change and try again
|
||||||
|
consumer.pops.wait(producer.lastPopRead, std::memory_order_relaxed);
|
||||||
|
producer.lastPopRead = consumer.pops.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
slots[producer.pushesNonAtomic++ & slotCountMask] = std::move(t);
|
||||||
|
// seq_cst so that the notify can't be ordered before the store
|
||||||
|
producer.pushes.store(producer.pushesNonAtomic, std::memory_order_seq_cst);
|
||||||
|
// We have to notify every time, since we don't know if this is the last
|
||||||
|
// push ever
|
||||||
|
producer.pushes.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Must be called from the producer thread
|
||||||
|
uint32_t outstanding() {
|
||||||
|
return producer.pushesNonAtomic -
|
||||||
|
consumer.pops.load(std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if a call to push might block. Must be called from the
|
||||||
|
/// producer thread.
|
||||||
|
bool wouldBlock() {
|
||||||
|
// See if we can determine that overflow won't happen entirely from state
|
||||||
|
// local to the producer
|
||||||
|
if (producer.pushesNonAtomic - producer.lastPopRead == slotCount - 1) {
|
||||||
|
// Re-read pops with memory order
|
||||||
|
producer.lastPopRead = consumer.pops.load(std::memory_order_acquire);
|
||||||
|
return producer.pushesNonAtomic - producer.lastPopRead == slotCount - 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Valid until the next pop, or until this queue is destroyed.
|
||||||
|
T *pop() {
|
||||||
|
// See if we can determine that there's an entry we can pop entirely from
|
||||||
|
// state local to the consumer
|
||||||
|
if (consumer.lastPushRead - consumer.popsNonAtomic == 0) {
|
||||||
|
// Re-read pushes with memory order and try again
|
||||||
|
consumer.lastPushRead = producer.pushes.load(std::memory_order_acquire);
|
||||||
|
if (consumer.lastPushRead - consumer.popsNonAtomic == 0) {
|
||||||
|
// Wait for pushes to change and try again
|
||||||
|
producer.pushes.wait(consumer.lastPushRead, std::memory_order_relaxed);
|
||||||
|
consumer.lastPushRead = producer.pushes.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto result = &slots[consumer.popsNonAtomic++ & slotCountMask];
|
||||||
|
// We only have to write pops with memory order if we've run out of items.
|
||||||
|
// We know that we'll eventually run out.
|
||||||
|
if (consumer.lastPushRead - consumer.popsNonAtomic == 0) {
|
||||||
|
// seq_cst so that the notify can't be ordered before the store
|
||||||
|
consumer.pops.store(consumer.popsNonAtomic, std::memory_order_seq_cst);
|
||||||
|
consumer.pops.notify_one();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint32_t slotCount;
|
||||||
|
const uint32_t slotCountMask;
|
||||||
|
T *slots;
|
||||||
|
struct alignas(kCacheLine) ProducerState {
|
||||||
|
std::atomic<uint32_t> pushes{0};
|
||||||
|
uint32_t pushesNonAtomic{0};
|
||||||
|
uint32_t lastPopRead{0};
|
||||||
|
};
|
||||||
|
struct alignas(kCacheLine) ConsumerState {
|
||||||
|
std::atomic<uint32_t> pops{0};
|
||||||
|
uint32_t popsNonAtomic{0};
|
||||||
|
uint32_t lastPushRead{0};
|
||||||
|
};
|
||||||
|
ProducerState producer;
|
||||||
|
ConsumerState consumer;
|
||||||
|
};
|
||||||
|
|
||||||
std::atomic<int64_t> transactions;
|
std::atomic<int64_t> transactions;
|
||||||
|
|
||||||
constexpr int kWindowSize = 10000000;
|
int64_t safeUnaryMinus(int64_t x) {
|
||||||
|
return x == std::numeric_limits<int64_t>::min() ? x : -x;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr int kNumPrefixes = 250000;
|
void tupleAppend(std::string &output, int64_t value) {
|
||||||
|
if (value == 0) {
|
||||||
|
output.push_back(0x14);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t size = 8 - __builtin_clrsbll(value) / 8;
|
||||||
|
int typeCode = 0x14 + (value < 0 ? -1 : 1) * size;
|
||||||
|
output.push_back(typeCode);
|
||||||
|
if (value < 0) {
|
||||||
|
value = ~safeUnaryMinus(value);
|
||||||
|
}
|
||||||
|
uint64_t swap = __builtin_bswap64(value);
|
||||||
|
output.insert(output.end(), (uint8_t *)&swap + 8 - size,
|
||||||
|
(uint8_t *)&swap + 8);
|
||||||
|
}
|
||||||
|
|
||||||
std::string makeKey(int64_t num, int suffixLen) {
|
void tupleAppend(std::string &output, std::string_view value) {
|
||||||
|
output.push_back('\x02');
|
||||||
|
if (memchr(value.data(), '\x00', value.size()) != nullptr) {
|
||||||
|
for (auto c : value) {
|
||||||
|
if (c == '\x00') {
|
||||||
|
output.push_back('\x00');
|
||||||
|
output.push_back('\xff');
|
||||||
|
} else {
|
||||||
|
output.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.insert(output.end(), value.begin(), value.end());
|
||||||
|
}
|
||||||
|
output.push_back('\x00');
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Ts> std::string tupleKey(const Ts &...ts) {
|
||||||
std::string result;
|
std::string result;
|
||||||
result.resize(sizeof(int64_t) + suffixLen);
|
(tupleAppend(result, ts), ...);
|
||||||
int64_t be = __builtin_bswap64(num);
|
|
||||||
memcpy(result.data(), &be, sizeof(int64_t));
|
|
||||||
memset(result.data() + sizeof(int64_t), 0, suffixLen);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void workload(weaselab::ConflictSet *cs) {
|
constexpr int kTotalKeyRange = 1'000'000'000;
|
||||||
int64_t version = kWindowSize;
|
constexpr int kWindowSize = 1'000'000;
|
||||||
for (int i = 0; i < kNumPrefixes; ++i) {
|
constexpr int kNumReadKeysPerTx = 5;
|
||||||
for (int j = 0; j < 50; ++j) {
|
constexpr int kNumWriteKeysPerTx = 10;
|
||||||
weaselab::ConflictSet::WriteRange wr;
|
|
||||||
auto k = makeKey(i, j);
|
struct Transaction {
|
||||||
wr.begin.p = (const uint8_t *)k.data();
|
std::vector<std::string> keys;
|
||||||
wr.begin.len = k.size();
|
std::vector<weaselab::ConflictSet::ReadRange> reads;
|
||||||
wr.end.len = 0;
|
std::vector<weaselab::ConflictSet::WriteRange> writes;
|
||||||
cs->addWrites(&wr, 1, version);
|
int64_t version;
|
||||||
|
int64_t oldestVersion;
|
||||||
|
Transaction() = default;
|
||||||
|
explicit Transaction(int64_t version)
|
||||||
|
: version(version), oldestVersion(version - kWindowSize) {
|
||||||
|
std::vector<int64_t> keyIndices;
|
||||||
|
for (int i = 0; i < std::max(kNumReadKeysPerTx, kNumWriteKeysPerTx); ++i) {
|
||||||
|
keyIndices.push_back(rand() % kTotalKeyRange);
|
||||||
|
}
|
||||||
|
std::sort(keyIndices.begin(), keyIndices.end());
|
||||||
|
constexpr std::string_view fullString =
|
||||||
|
"this is a string, where a prefix of it is used as an element of the "
|
||||||
|
"tuple forming the key";
|
||||||
|
for (int i = 0; i < int(keyIndices.size()); ++i) {
|
||||||
|
keys.push_back(
|
||||||
|
tupleKey(0x100, keyIndices[i] / fullString.size(),
|
||||||
|
fullString.substr(0, keyIndices[i] % fullString.size())));
|
||||||
|
// printf("%s\n", printable(keys.back()).c_str());
|
||||||
|
}
|
||||||
|
for (int i = 0; i < kNumWriteKeysPerTx; ++i) {
|
||||||
|
writes.push_back({{(const uint8_t *)keys[i].data(), int(keys[i].size())},
|
||||||
|
{nullptr, 0}});
|
||||||
|
}
|
||||||
|
reads.push_back({{(const uint8_t *)keys[0].data(), int(keys[0].size())},
|
||||||
|
{(const uint8_t *)keys[1].data(), int(keys[1].size())},
|
||||||
|
version - std::min(10, kWindowSize)});
|
||||||
|
static_assert(kNumReadKeysPerTx >= 3);
|
||||||
|
for (int i = 2; i < kNumReadKeysPerTx; ++i) {
|
||||||
|
reads.push_back({{(const uint8_t *)keys[i].data(), int(keys[i].size())},
|
||||||
|
{nullptr, 0},
|
||||||
|
version - kWindowSize});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
++version;
|
|
||||||
for (int i = 0; i < kNumPrefixes; ++i) {
|
|
||||||
weaselab::ConflictSet::WriteRange wr;
|
|
||||||
auto k = makeKey(i, 50);
|
|
||||||
wr.begin.p = (const uint8_t *)k.data();
|
|
||||||
wr.begin.len = k.size();
|
|
||||||
wr.end.len = 0;
|
|
||||||
cs->addWrites(&wr, 1, version);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int kNumReads = 1;
|
Transaction(Transaction &&) = default;
|
||||||
std::vector<weaselab::ConflictSet::Result> results(kNumReads);
|
Transaction &operator=(Transaction &&) = default;
|
||||||
for (;; transactions.fetch_add(1, std::memory_order_relaxed)) {
|
Transaction(Transaction const &) = delete;
|
||||||
std::vector<std::string> keys(kNumReads);
|
Transaction const &operator=(Transaction const &) = delete;
|
||||||
for (auto &k : keys) {
|
};
|
||||||
k = makeKey(rand() % kNumPrefixes, 49);
|
|
||||||
}
|
struct Resolver {
|
||||||
std::vector<weaselab::ConflictSet::ReadRange> reads(kNumReads);
|
|
||||||
for (int i = 0; i < reads.size(); ++i) {
|
void resolve(const weaselab::ConflictSet::ReadRange *reads, int readCount,
|
||||||
reads[i].begin.p = (const uint8_t *)(keys[i].data());
|
const weaselab::ConflictSet::WriteRange *writes, int writeCount,
|
||||||
reads[i].begin.len = keys[i].size();
|
int64_t newVersion, int64_t newOldestVersion) {
|
||||||
reads[i].end.len = 0;
|
results.resize(readCount);
|
||||||
reads[i].readVersion = version - 1;
|
cs.check(reads, results.data(), readCount);
|
||||||
}
|
cs.addWrites(writes, writeCount, newVersion);
|
||||||
cs->check(reads.data(), results.data(), kNumReads);
|
cs.setOldestVersion(newOldestVersion);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
ConflictSet cs{0};
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<weaselab::ConflictSet::Result> results;
|
||||||
|
};
|
||||||
|
|
||||||
// Adapted from getaddrinfo man page
|
// Adapted from getaddrinfo man page
|
||||||
int getListenFd(const char *node, const char *service) {
|
int getListenFd(const char *node, const char *service) {
|
||||||
@@ -216,7 +366,8 @@ int main(int argc, char **argv) {
|
|||||||
{
|
{
|
||||||
int listenFd = getListenFd(argv[1], argv[2]);
|
int listenFd = getListenFd(argv[1], argv[2]);
|
||||||
|
|
||||||
weaselab::ConflictSet cs{0};
|
Resolver resolver;
|
||||||
|
auto &cs = resolver.cs;
|
||||||
weaselab::ConflictSet::MetricsV1 *metrics;
|
weaselab::ConflictSet::MetricsV1 *metrics;
|
||||||
int metricsCount;
|
int metricsCount;
|
||||||
cs.getMetricsV1(&metrics, &metricsCount);
|
cs.getMetricsV1(&metrics, &metricsCount);
|
||||||
@@ -265,7 +416,22 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto w = std::thread{workload, &cs};
|
TxQueue<Transaction> queue{10};
|
||||||
|
|
||||||
|
auto workloadThread = std::thread{[&]() {
|
||||||
|
for (int64_t version = kWindowSize;;
|
||||||
|
++version, transactions.fetch_add(1, std::memory_order_relaxed)) {
|
||||||
|
queue.push(Transaction(version));
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
auto resolverThread = std::thread{[&]() {
|
||||||
|
for (;;) {
|
||||||
|
auto tx = queue.pop();
|
||||||
|
resolver.resolve(tx->reads.data(), tx->reads.size(), tx->writes.data(),
|
||||||
|
tx->writes.size(), tx->version, tx->oldestVersion);
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct sockaddr_storage peer_addr = {};
|
struct sockaddr_storage peer_addr = {};
|
||||||
|
@@ -767,7 +767,9 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
false, true);
|
false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
sortPoints(points);
|
if (!std::is_sorted(points.begin(), points.end())) {
|
||||||
|
sortPoints(points);
|
||||||
|
}
|
||||||
|
|
||||||
int activeWriteCount = 0;
|
int activeWriteCount = 0;
|
||||||
std::vector<std::pair<StringRef, StringRef>> combinedWriteConflictRanges;
|
std::vector<std::pair<StringRef, StringRef>> combinedWriteConflictRanges;
|
||||||
@@ -794,7 +796,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
int temp[stripeSize];
|
int temp[stripeSize];
|
||||||
int stripes = (stringCount + stripeSize - 1) / stripeSize;
|
int stripes = (stringCount + stripeSize - 1) / stripeSize;
|
||||||
StringRef values[stripeSize];
|
StringRef values[stripeSize];
|
||||||
int64_t writeVersions[stripeSize / 2];
|
|
||||||
int ss = stringCount - (stripes - 1) * stripeSize;
|
int ss = stringCount - (stripes - 1) * stripeSize;
|
||||||
int64_t entryDelta = 0;
|
int64_t entryDelta = 0;
|
||||||
for (int s = stripes - 1; s >= 0; s--) {
|
for (int s = stripes - 1; s >= 0; s--) {
|
||||||
|
@@ -5,6 +5,7 @@ __stack_chk_guard@GLIBC_2.17
|
|||||||
abort@GLIBC_2.17
|
abort@GLIBC_2.17
|
||||||
free@GLIBC_2.17
|
free@GLIBC_2.17
|
||||||
malloc@GLIBC_2.17
|
malloc@GLIBC_2.17
|
||||||
|
memcmp@GLIBC_2.17
|
||||||
memcpy@GLIBC_2.17
|
memcpy@GLIBC_2.17
|
||||||
memmove@GLIBC_2.17
|
memmove@GLIBC_2.17
|
||||||
memset@GLIBC_2.17
|
memset@GLIBC_2.17
|
@@ -1,7 +1,7 @@
|
|||||||
set(CMAKE_SYSTEM_NAME Linux)
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||||
set(CMAKE_C_COMPILER "/usr/bin/aarch64-linux-gnu-gcc")
|
set(CMAKE_C_COMPILER "clang;--target=aarch64-linux-gnu")
|
||||||
set(CMAKE_CXX_COMPILER "/usr/bin/aarch64-linux-gnu-g++")
|
set(CMAKE_CXX_COMPILER "clang++;--target=aarch64-linux-gnu")
|
||||||
set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu)
|
set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu)
|
||||||
set(CMAKE_CROSSCOMPILING_EMULATOR "qemu-aarch64;-L;/usr/aarch64-linux-gnu/")
|
set(CMAKE_CROSSCOMPILING_EMULATOR "qemu-aarch64;-L;/usr/aarch64-linux-gnu/")
|
||||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE arm64)
|
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE arm64)
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
___chkstk_darwin
|
||||||
___stack_chk_fail
|
___stack_chk_fail
|
||||||
___stack_chk_guard
|
___stack_chk_guard
|
||||||
__tlv_bootstrap
|
__tlv_bootstrap
|
||||||
@@ -5,6 +6,7 @@ _abort
|
|||||||
_bzero
|
_bzero
|
||||||
_free
|
_free
|
||||||
_malloc
|
_malloc
|
||||||
|
_memcmp
|
||||||
_memcpy
|
_memcpy
|
||||||
_memmove
|
_memmove
|
||||||
dyld_stub_binder
|
dyld_stub_binder
|
BIN
corpus/00c2f9be831326008b88fa8daa1f6a2ba54ff0ab
Normal file
BIN
corpus/00c2f9be831326008b88fa8daa1f6a2ba54ff0ab
Normal file
Binary file not shown.
BIN
corpus/00c877491b1fcc8bb8fb36874a7922de7f3f4df2
Normal file
BIN
corpus/00c877491b1fcc8bb8fb36874a7922de7f3f4df2
Normal file
Binary file not shown.
BIN
corpus/00df1fd720151ee1fb20574f080e75190d715723
Normal file
BIN
corpus/00df1fd720151ee1fb20574f080e75190d715723
Normal file
Binary file not shown.
BIN
corpus/01700660cf8938f7861559ae8f5fc00a55532679
Normal file
BIN
corpus/01700660cf8938f7861559ae8f5fc00a55532679
Normal file
Binary file not shown.
BIN
corpus/026c293f183c14c6f173718d432b73f41e19cba8
Normal file
BIN
corpus/026c293f183c14c6f173718d432b73f41e19cba8
Normal file
Binary file not shown.
BIN
corpus/02b4c0e1317cc3d71ca9d05d3d855c9d0fbed0ed
Normal file
BIN
corpus/02b4c0e1317cc3d71ca9d05d3d855c9d0fbed0ed
Normal file
Binary file not shown.
BIN
corpus/033c4c71cb5ca5a3a933b9001be1d4246784fefb
Normal file
BIN
corpus/033c4c71cb5ca5a3a933b9001be1d4246784fefb
Normal file
Binary file not shown.
BIN
corpus/035247cc26d90aee0b4f9560833e5a495d890159
Normal file
BIN
corpus/035247cc26d90aee0b4f9560833e5a495d890159
Normal file
Binary file not shown.
BIN
corpus/03680111265d5f0b8816feb73069cf1f6538d4dd
Normal file
BIN
corpus/03680111265d5f0b8816feb73069cf1f6538d4dd
Normal file
Binary file not shown.
BIN
corpus/0381a9a3c6ea140cdd7ec8cf73eb2c56e01f8d54
Normal file
BIN
corpus/0381a9a3c6ea140cdd7ec8cf73eb2c56e01f8d54
Normal file
Binary file not shown.
BIN
corpus/03cbf22d59d0005921ca3e3c725fc9c165f9e873
Normal file
BIN
corpus/03cbf22d59d0005921ca3e3c725fc9c165f9e873
Normal file
Binary file not shown.
BIN
corpus/03d3918b737a86ed38fbeae6dff198d6913b90b2
Normal file
BIN
corpus/03d3918b737a86ed38fbeae6dff198d6913b90b2
Normal file
Binary file not shown.
BIN
corpus/04228353f0feb04662eebbe15dab859927d87982
Normal file
BIN
corpus/04228353f0feb04662eebbe15dab859927d87982
Normal file
Binary file not shown.
BIN
corpus/042c4df1a3357a2b015db64e8e6b09549d3655c5
Normal file
BIN
corpus/042c4df1a3357a2b015db64e8e6b09549d3655c5
Normal file
Binary file not shown.
BIN
corpus/04338408516abc9c563802aadc522db002e0a5d0
Normal file
BIN
corpus/04338408516abc9c563802aadc522db002e0a5d0
Normal file
Binary file not shown.
BIN
corpus/04c53e268f5d34ac6033f80672ebf9b48975cfc8
Normal file
BIN
corpus/04c53e268f5d34ac6033f80672ebf9b48975cfc8
Normal file
Binary file not shown.
BIN
corpus/04c65b5774374b94914863a1c244cd4ca26873d2
Normal file
BIN
corpus/04c65b5774374b94914863a1c244cd4ca26873d2
Normal file
Binary file not shown.
BIN
corpus/051590b47c5269306a3a8894eb3d72d86c4a6e71
Normal file
BIN
corpus/051590b47c5269306a3a8894eb3d72d86c4a6e71
Normal file
Binary file not shown.
BIN
corpus/05184b61aacd101ea39bc6f3b9985fec132b8125
Normal file
BIN
corpus/05184b61aacd101ea39bc6f3b9985fec132b8125
Normal file
Binary file not shown.
BIN
corpus/054623afeda876d353806d81077181229affdd36
Normal file
BIN
corpus/054623afeda876d353806d81077181229affdd36
Normal file
Binary file not shown.
BIN
corpus/0558cbe0f7b69d3e129a95d07a67e6bcd737f280
Normal file
BIN
corpus/0558cbe0f7b69d3e129a95d07a67e6bcd737f280
Normal file
Binary file not shown.
BIN
corpus/056fee409c5511f6a7456cd4791d9385f6d5ebbe
Normal file
BIN
corpus/056fee409c5511f6a7456cd4791d9385f6d5ebbe
Normal file
Binary file not shown.
BIN
corpus/05802ff3945dce77412442bf5888cc26c29c56f1
Normal file
BIN
corpus/05802ff3945dce77412442bf5888cc26c29c56f1
Normal file
Binary file not shown.
BIN
corpus/05a237bf01382822789d33bda1b24298e13bb031
Normal file
BIN
corpus/05a237bf01382822789d33bda1b24298e13bb031
Normal file
Binary file not shown.
BIN
corpus/060d0c1be7331609f5b8c1d1201bc06c1b203c21
Normal file
BIN
corpus/060d0c1be7331609f5b8c1d1201bc06c1b203c21
Normal file
Binary file not shown.
BIN
corpus/061a5fd2f5e90098ec417feda11d43b7ff3ecb79
Normal file
BIN
corpus/061a5fd2f5e90098ec417feda11d43b7ff3ecb79
Normal file
Binary file not shown.
BIN
corpus/065ec99952bffeb53f340d8cee645654f5b1e891
Normal file
BIN
corpus/065ec99952bffeb53f340d8cee645654f5b1e891
Normal file
Binary file not shown.
BIN
corpus/0677708940f8c88cd48e841993d34838d9b1215e
Normal file
BIN
corpus/0677708940f8c88cd48e841993d34838d9b1215e
Normal file
Binary file not shown.
BIN
corpus/069fd605e510b2218cf1b10ec79ae00763aeb195
Normal file
BIN
corpus/069fd605e510b2218cf1b10ec79ae00763aeb195
Normal file
Binary file not shown.
BIN
corpus/0707680f7d9ce11dd30c6536f05848d598fb27d4
Normal file
BIN
corpus/0707680f7d9ce11dd30c6536f05848d598fb27d4
Normal file
Binary file not shown.
BIN
corpus/0707d9709690c9700f27fd73d97c0325fa81c162
Normal file
BIN
corpus/0707d9709690c9700f27fd73d97c0325fa81c162
Normal file
Binary file not shown.
BIN
corpus/0771614f4aee61a932eb4f6cec1f736fce997a1e
Normal file
BIN
corpus/0771614f4aee61a932eb4f6cec1f736fce997a1e
Normal file
Binary file not shown.
BIN
corpus/07854cf6f54c192387047cfc49a65e4b1bdca4a1
Normal file
BIN
corpus/07854cf6f54c192387047cfc49a65e4b1bdca4a1
Normal file
Binary file not shown.
BIN
corpus/078875343814fb2f6f7be30e0fd58a139d977f19
Normal file
BIN
corpus/078875343814fb2f6f7be30e0fd58a139d977f19
Normal file
Binary file not shown.
BIN
corpus/080d022ba31789a6276dbf9c7796f05cc9559c36
Normal file
BIN
corpus/080d022ba31789a6276dbf9c7796f05cc9559c36
Normal file
Binary file not shown.
BIN
corpus/086ae03d7492047d12383776a7a2dd10acb6a030
Normal file
BIN
corpus/086ae03d7492047d12383776a7a2dd10acb6a030
Normal file
Binary file not shown.
BIN
corpus/08bd213542d71b1e07b7cafeba9816e2990278b6
Normal file
BIN
corpus/08bd213542d71b1e07b7cafeba9816e2990278b6
Normal file
Binary file not shown.
BIN
corpus/08f6fcd47ba57d41f5cae4a040e8318fc2f653da
Normal file
BIN
corpus/08f6fcd47ba57d41f5cae4a040e8318fc2f653da
Normal file
Binary file not shown.
BIN
corpus/08fb0c9ae5f25f3040bb0a1489ff0dc0b537ebfa
Normal file
BIN
corpus/08fb0c9ae5f25f3040bb0a1489ff0dc0b537ebfa
Normal file
Binary file not shown.
BIN
corpus/097e37993adeed2f667efe74003d98b0cd90c5d8
Normal file
BIN
corpus/097e37993adeed2f667efe74003d98b0cd90c5d8
Normal file
Binary file not shown.
BIN
corpus/09b0a61939d3133f61a4b0aaee5149503e3019a1
Normal file
BIN
corpus/09b0a61939d3133f61a4b0aaee5149503e3019a1
Normal file
Binary file not shown.
BIN
corpus/09c0b1f06a1e9bfdfb8842ec414f97ade10cddf4
Normal file
BIN
corpus/09c0b1f06a1e9bfdfb8842ec414f97ade10cddf4
Normal file
Binary file not shown.
BIN
corpus/09d49cebef016c9caf2c3efe971375557329053b
Normal file
BIN
corpus/09d49cebef016c9caf2c3efe971375557329053b
Normal file
Binary file not shown.
BIN
corpus/09eb955d066ba378b772ae39b5402fc346869b92
Normal file
BIN
corpus/09eb955d066ba378b772ae39b5402fc346869b92
Normal file
Binary file not shown.
BIN
corpus/0a0da5b17a24b0282501d2f380dc52aefd4d9b9f
Normal file
BIN
corpus/0a0da5b17a24b0282501d2f380dc52aefd4d9b9f
Normal file
Binary file not shown.
BIN
corpus/0b43bd12f2b7df4397072b128c1eac80fc308b47
Normal file
BIN
corpus/0b43bd12f2b7df4397072b128c1eac80fc308b47
Normal file
Binary file not shown.
BIN
corpus/0b93fbf7c443c8403e0c3ee6cd3d9498aa9aaeb0
Normal file
BIN
corpus/0b93fbf7c443c8403e0c3ee6cd3d9498aa9aaeb0
Normal file
Binary file not shown.
BIN
corpus/0baea27108df93d537bcc0de459495d5f17382a0
Normal file
BIN
corpus/0baea27108df93d537bcc0de459495d5f17382a0
Normal file
Binary file not shown.
BIN
corpus/0bb1476984cada2ca3fc922dd918f0d2df54114c
Normal file
BIN
corpus/0bb1476984cada2ca3fc922dd918f0d2df54114c
Normal file
Binary file not shown.
BIN
corpus/0bee3319fe0f3462a7f0cb7c8eeb616d4660add7
Normal file
BIN
corpus/0bee3319fe0f3462a7f0cb7c8eeb616d4660add7
Normal file
Binary file not shown.
BIN
corpus/0c71425d945565f739bdf33d02d9a2f80fe81c29
Normal file
BIN
corpus/0c71425d945565f739bdf33d02d9a2f80fe81c29
Normal file
Binary file not shown.
BIN
corpus/0c757a21c9d2629c51923f943dc2c79c4bcbca4a
Normal file
BIN
corpus/0c757a21c9d2629c51923f943dc2c79c4bcbca4a
Normal file
Binary file not shown.
BIN
corpus/0c80c84b1d1b8b157106f257cf9bf2fd404936d5
Normal file
BIN
corpus/0c80c84b1d1b8b157106f257cf9bf2fd404936d5
Normal file
Binary file not shown.
BIN
corpus/0c83b55eddb372f37fd479b982a26f7d76a9ee74
Normal file
BIN
corpus/0c83b55eddb372f37fd479b982a26f7d76a9ee74
Normal file
Binary file not shown.
BIN
corpus/0cb7fd64803ef442156dab03223d5cca8d8ee899
Normal file
BIN
corpus/0cb7fd64803ef442156dab03223d5cca8d8ee899
Normal file
Binary file not shown.
BIN
corpus/0cbb486e842f843588f084c6480e42e2cfef60b2
Normal file
BIN
corpus/0cbb486e842f843588f084c6480e42e2cfef60b2
Normal file
Binary file not shown.
BIN
corpus/0cfc86eecaf16f682bcce978ce41d35a016a0a7f
Normal file
BIN
corpus/0cfc86eecaf16f682bcce978ce41d35a016a0a7f
Normal file
Binary file not shown.
BIN
corpus/0d19837d6411c43e7e7c3f8ae592719fd1e556e2
Normal file
BIN
corpus/0d19837d6411c43e7e7c3f8ae592719fd1e556e2
Normal file
Binary file not shown.
BIN
corpus/0d28b7cc8c4d9359f045df42f88dd30ee52b8477
Normal file
BIN
corpus/0d28b7cc8c4d9359f045df42f88dd30ee52b8477
Normal file
Binary file not shown.
BIN
corpus/0d35b148f45f7e3f722f4ac298558ba0dd545b48
Normal file
BIN
corpus/0d35b148f45f7e3f722f4ac298558ba0dd545b48
Normal file
Binary file not shown.
BIN
corpus/0dea4eac572bd1210f5cf582c4dc049696bfd3a3
Normal file
BIN
corpus/0dea4eac572bd1210f5cf582c4dc049696bfd3a3
Normal file
Binary file not shown.
BIN
corpus/0e2c82cd38130dc94263a67b46afbf89407eee2a
Normal file
BIN
corpus/0e2c82cd38130dc94263a67b46afbf89407eee2a
Normal file
Binary file not shown.
BIN
corpus/0e3aaaf8e085bdf5f4419b176cea97d4bfcb62bf
Normal file
BIN
corpus/0e3aaaf8e085bdf5f4419b176cea97d4bfcb62bf
Normal file
Binary file not shown.
BIN
corpus/0eb983ee4da4177894988ab187e0d17719df3c3e
Normal file
BIN
corpus/0eb983ee4da4177894988ab187e0d17719df3c3e
Normal file
Binary file not shown.
BIN
corpus/0ebb66b9b7a11c4858236dc5852386dedae328c0
Normal file
BIN
corpus/0ebb66b9b7a11c4858236dc5852386dedae328c0
Normal file
Binary file not shown.
BIN
corpus/0f1d504244bcffbad21d5b849e245326f62807ff
Normal file
BIN
corpus/0f1d504244bcffbad21d5b849e245326f62807ff
Normal file
Binary file not shown.
BIN
corpus/0fbd6aa91e6a6c89f575d339b9f103a057b80ba6
Normal file
BIN
corpus/0fbd6aa91e6a6c89f575d339b9f103a057b80ba6
Normal file
Binary file not shown.
BIN
corpus/1023a1cc9e57b90b3c975ba77c8f5a177e999875
Normal file
BIN
corpus/1023a1cc9e57b90b3c975ba77c8f5a177e999875
Normal file
Binary file not shown.
BIN
corpus/1030748ff092d1b4ec3d30d7b68ba29d895b4b7a
Normal file
BIN
corpus/1030748ff092d1b4ec3d30d7b68ba29d895b4b7a
Normal file
Binary file not shown.
BIN
corpus/10550b94427665b340d6201df040db42d9d80f51
Normal file
BIN
corpus/10550b94427665b340d6201df040db42d9d80f51
Normal file
Binary file not shown.
BIN
corpus/10585791c59c9e43299c8958b48245d705addf47
Normal file
BIN
corpus/10585791c59c9e43299c8958b48245d705addf47
Normal file
Binary file not shown.
BIN
corpus/115428a9c006c54696c148fd767af66ca4d10d3a
Normal file
BIN
corpus/115428a9c006c54696c148fd767af66ca4d10d3a
Normal file
Binary file not shown.
BIN
corpus/11570d892b76b3cdfc2b4d05d4424b5668e295a1
Normal file
BIN
corpus/11570d892b76b3cdfc2b4d05d4424b5668e295a1
Normal file
Binary file not shown.
BIN
corpus/117bea9f82fbe640745537fbc7177bccc37d1335
Normal file
BIN
corpus/117bea9f82fbe640745537fbc7177bccc37d1335
Normal file
Binary file not shown.
BIN
corpus/11c2ff6e154050876cce57fa4b2122f74282e082
Normal file
BIN
corpus/11c2ff6e154050876cce57fa4b2122f74282e082
Normal file
Binary file not shown.
BIN
corpus/11ebd31c17d648c7c9fbdda49afb4898647f04e1
Normal file
BIN
corpus/11ebd31c17d648c7c9fbdda49afb4898647f04e1
Normal file
Binary file not shown.
BIN
corpus/121b43d1853a0dea379afbd10fe00469aad22e40
Normal file
BIN
corpus/121b43d1853a0dea379afbd10fe00469aad22e40
Normal file
Binary file not shown.
BIN
corpus/1238fee9b77c9426b7a2a358216792729766b923
Normal file
BIN
corpus/1238fee9b77c9426b7a2a358216792729766b923
Normal file
Binary file not shown.
BIN
corpus/1288f1214d6a6cd3cbe15a1d23fb360991cb93f6
Normal file
BIN
corpus/1288f1214d6a6cd3cbe15a1d23fb360991cb93f6
Normal file
Binary file not shown.
BIN
corpus/12a8e5475cb4612eb6a4f67249f9f41f3b860a2e
Normal file
BIN
corpus/12a8e5475cb4612eb6a4f67249f9f41f3b860a2e
Normal file
Binary file not shown.
BIN
corpus/12e31d99ae65da7d9d6bcb04c6bd97422a85d309
Normal file
BIN
corpus/12e31d99ae65da7d9d6bcb04c6bd97422a85d309
Normal file
Binary file not shown.
BIN
corpus/1319ce414e7cd478b06628f9951e7620134cbbf2
Normal file
BIN
corpus/1319ce414e7cd478b06628f9951e7620134cbbf2
Normal file
Binary file not shown.
BIN
corpus/136ad900e11b346cf1ef2d3b0a2a94ce6a17e797
Normal file
BIN
corpus/136ad900e11b346cf1ef2d3b0a2a94ce6a17e797
Normal file
Binary file not shown.
BIN
corpus/136c9552d2addd4e4796bb87ea2a26d5c18bc9c6
Normal file
BIN
corpus/136c9552d2addd4e4796bb87ea2a26d5c18bc9c6
Normal file
Binary file not shown.
BIN
corpus/137f0707639206c6829f2fadb5f2afe28ccc28ca
Normal file
BIN
corpus/137f0707639206c6829f2fadb5f2afe28ccc28ca
Normal file
Binary file not shown.
BIN
corpus/13c843559282b726977d85eacaf35a826527c96b
Normal file
BIN
corpus/13c843559282b726977d85eacaf35a826527c96b
Normal file
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