diff --git a/Bench.cpp b/Bench.cpp index 35866b5..684e694 100644 --- a/Bench.cpp +++ b/Bench.cpp @@ -1,4 +1,5 @@ #include "ConflictSet.h" +#include "Internal.h" #define ANKERL_NANOBENCH_IMPLEMENT #include "third_party/nanobench.h" @@ -15,7 +16,7 @@ std::string toKey(int n) { constexpr int kNumKeys = 100000; -int main(void) { +void benchPointRead() { ankerl::nanobench::Bench bench; int readKey = kNumKeys / 2; @@ -42,4 +43,66 @@ int main(void) { r.readVersion = 0; ConflictSet::Result result; bench.run("point read", [&]() { cs.check(&r, &result, 1); }); +} + +void benchPointerSet() { + ankerl::nanobench::Bench bench; + + constexpr int kNumPointers = 32; + bench.batch(kNumPointers); + + std::vector pointers; + for (int i = 0; i < kNumPointers; ++i) { + pointers.push_back(malloc(1)); + } + + bench.run("Create and destroy Arena hashset", [&]() { + Arena arena; + auto h = hashSet(arena); + for (auto p : pointers) { + h.insert(p); + } + }); + + bench.run("Create and destroy malloc hashset", [&]() { + std::unordered_set> h; + for (auto p : pointers) { + h.insert(p); + } + }); + + bench.run("Create and destroy Arena vector", [&]() { + Arena arena; + auto h = vector(arena); + for (auto p : pointers) { + h.push_back(p); + } + }); + + { + Arena arena; + auto h = hashSet(arena); + bench.run("Find hashset", [&]() { + for (auto p : pointers) { + bench.doNotOptimizeAway(h.find(p)); + } + }); + } + + { + bench.run("Find vector", [&]() { + for (auto p : pointers) { + bench.doNotOptimizeAway(std::find(pointers.begin(), pointers.end(), p)); + } + }); + } + + for (auto p : pointers) { + free(p); + } +} + +int main(void) { + // benchPointRead(); + benchPointerSet(); } \ No newline at end of file diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 049b95f..e167e28 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -43,7 +43,7 @@ struct Node { int16_t numChildren = 0; bool entryPresent = false; uint8_t parentsIndex = 0; - constexpr static auto kPartialKeyMaxLen = 10; + constexpr static auto kPartialKeyMaxLen = 26; uint8_t partialKey[kPartialKeyMaxLen]; int8_t partialKeyLen = 0; /* end section that's copied to the next node */ @@ -730,25 +730,37 @@ bool checkRangeRead(Node *n, const std::span begin, while (!left.step()) ; } + if (!rightDone) { while (!right.step()) ; } - Arena arena; - auto leftPath = vector(arena); - auto rightPath = vector(arena); - for (auto *iter = left.n; iter != nullptr; iter = iter->parent) { - leftPath.push_back(iter); - } - for (auto *iter = right.n; iter != nullptr; iter = iter->parent) { - rightPath.push_back(iter); + Arena arena{64 << 10}; + // auto leftBorder = hashSet(arena); + // auto rightBorder = hashSet(arena); + auto leftBorder = vector(arena); + auto rightBorder = vector(arena); + { + auto *l = left.n; + auto *r = right.n; + for (; l != nullptr && r != nullptr; l = l->parent, r = r->parent) { + leftBorder.push_back(l); + rightBorder.push_back(r); + } + for (; l != nullptr; l = l->parent) { + leftBorder.push_back(l); + } + for (; r != nullptr; r = r->parent) { + rightBorder.push_back(r); + } } + #if DEBUG_VERBOSE && !defined(NDEBUG) fprintf(stderr, "firstGeq for `%s' got `%s'\n", printable(begin).c_str(), - getSearchPath(left.n).c_str()); + getSearchPathPrintable(left.n).c_str()); fprintf(stderr, "firstGeq for `%s' got `%s'\n", printable(end).c_str(), - getSearchPath(right.n).c_str()); + getSearchPathPrintable(right.n).c_str()); #endif if (left.n != nullptr && left.cmp != 0 && @@ -764,12 +776,14 @@ bool checkRangeRead(Node *n, const std::span begin, } // TODO better data structure for pointer set. Also collect during first - // traversal. + // traversal? for (auto *iter = nextPhysical(left.n); iter != right.n;) { - const bool onLeftPath = - std::find(leftPath.begin(), leftPath.end(), iter) != leftPath.end(); - const bool onRightPath = - std::find(rightPath.begin(), rightPath.end(), iter) != rightPath.end(); + // const bool onLeftPath = leftBorder.find(iter) != leftBorder.end(); + // const bool onRightPath = rightBorder.find(iter) != rightBorder.end(); + const bool onLeftPath = std::find(leftBorder.begin(), leftBorder.end(), + iter) != leftBorder.end(); + const bool onRightPath = std::find(rightBorder.begin(), rightBorder.end(), + iter) != rightBorder.end(); if (!onLeftPath && !onRightPath) { if (iter->maxVersion > readVersion) { return false; diff --git a/Internal.h b/Internal.h index cd8a457..47d3476 100644 --- a/Internal.h +++ b/Internal.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -184,9 +185,20 @@ template using Set = std::set, ArenaAlloc>; template auto set(Arena &arena) { return Set(ArenaAlloc(&arena)); } + +template struct MyHash; + +template struct MyHash { + size_t operator()(const T *t) const noexcept { + size_t result; + memcpy(&result, &t, sizeof(result)); + return result; + } +}; + template using HashSet = - std::unordered_set, std::equal_to, ArenaAlloc>; + std::unordered_set, std::equal_to, ArenaAlloc>; template auto hashSet(Arena &arena) { return HashSet(ArenaAlloc(&arena)); } @@ -449,7 +461,7 @@ template struct TestDriver { ConflictSetImpl cs{writeVersion}; ReferenceImpl refImpl{writeVersion}; - constexpr static auto kMaxKeyLen = 24; + constexpr static auto kMaxKeyLen = 32; bool ok = true;