Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
@@ -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,9 +48,10 @@ 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};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,14 +82,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?
|
||||||
|
|||||||
+1408
-512
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -45,7 +45,7 @@ RUN curl -Ls https://sourceware.org/pub/valgrind/valgrind-3.22.0.tar.bz2 -o valg
|
|||||||
# Recent clang
|
# Recent clang
|
||||||
RUN wget https://apt.llvm.org/llvm.sh && chmod +x ./llvm.sh && ./llvm.sh 20
|
RUN wget https://apt.llvm.org/llvm.sh && chmod +x ./llvm.sh && ./llvm.sh 20
|
||||||
|
|
||||||
RUN apt-get install clang
|
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
|
||||||
|
|||||||
+48
-10
@@ -26,9 +26,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 +67,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 +75,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
|
||||||
@@ -569,7 +609,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 +717,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);
|
||||||
|
|||||||
+12
-32
@@ -1,5 +1,6 @@
|
|||||||
#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>
|
||||||
@@ -37,41 +38,20 @@ std::string makeKey(int64_t num, int suffixLen) {
|
|||||||
|
|
||||||
void workload(weaselab::ConflictSet *cs) {
|
void workload(weaselab::ConflictSet *cs) {
|
||||||
int64_t version = kWindowSize;
|
int64_t version = kWindowSize;
|
||||||
for (int i = 0; i < kNumPrefixes; ++i) {
|
constexpr int kNumWrites = 16;
|
||||||
for (int j = 0; j < 50; ++j) {
|
|
||||||
weaselab::ConflictSet::WriteRange wr;
|
|
||||||
auto k = makeKey(i, j);
|
|
||||||
wr.begin.p = (const uint8_t *)k.data();
|
|
||||||
wr.begin.len = k.size();
|
|
||||||
wr.end.len = 0;
|
|
||||||
cs->addWrites(&wr, 1, version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++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;
|
|
||||||
std::vector<weaselab::ConflictSet::Result> results(kNumReads);
|
|
||||||
for (;; transactions.fetch_add(1, std::memory_order_relaxed)) {
|
for (;; transactions.fetch_add(1, std::memory_order_relaxed)) {
|
||||||
std::vector<std::string> keys(kNumReads);
|
std::vector<std::string> keys;
|
||||||
for (auto &k : keys) {
|
std::vector<weaselab::ConflictSet::WriteRange> writes;
|
||||||
k = makeKey(rand() % kNumPrefixes, 49);
|
for (int i = 0; i < kNumWrites; ++i) {
|
||||||
|
keys.push_back(makeKey(rand() % kNumPrefixes, rand() % 50));
|
||||||
}
|
}
|
||||||
std::vector<weaselab::ConflictSet::ReadRange> reads(kNumReads);
|
for (int i = 0; i < kNumWrites; ++i) {
|
||||||
for (int i = 0; i < reads.size(); ++i) {
|
writes.push_back({{(const uint8_t *)keys[i].data(), int(keys[i].size())},
|
||||||
reads[i].begin.p = (const uint8_t *)(keys[i].data());
|
{nullptr, 0}});
|
||||||
reads[i].begin.len = keys[i].size();
|
|
||||||
reads[i].end.len = 0;
|
|
||||||
reads[i].readVersion = version - 1;
|
|
||||||
}
|
}
|
||||||
cs->check(reads.data(), results.data(), kNumReads);
|
cs->addWrites(writes.data(), writes.size(), version);
|
||||||
|
cs->setOldestVersion(version - kWindowSize);
|
||||||
|
++version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user