From ee3361952aa5c8256d1017018abfc360213df95b Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Thu, 22 Aug 2024 17:00:15 -0700 Subject: [PATCH] Use better rng in skip list low bits of lcg have low periods --- SkipList.cpp | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/SkipList.cpp b/SkipList.cpp index 2e5a477..cff2f09 100644 --- a/SkipList.cpp +++ b/SkipList.cpp @@ -183,13 +183,6 @@ void sortPoints(std::vector &points) { } } -static thread_local uint32_t g_seed = 0; - -static inline int skfastrand() { - g_seed = g_seed * 1664525L + 1013904223L; - return g_seed; -} - static int compare(const StringRef &a, const StringRef &b) { int c = memcmp(a.data(), b.data(), std::min(a.size(), b.size())); if (c < 0) @@ -215,20 +208,24 @@ struct ReadConflictRange { } }; +static constexpr int MaxLevels = 26; + +struct RandomLevel { + explicit RandomLevel(uint32_t seed) : seed(seed) {} + + int next() { + int result = __builtin_clz(seed | (uint32_t(-1) >> (MaxLevels - 1))); + seed = seed * 1664525L + 1013904223L; + return result; + } + +private: + uint32_t seed; +}; + class SkipList { private: - static constexpr int MaxLevels = 26; - - int randomLevel() const { - uint32_t i = uint32_t(skfastrand()) >> (32 - (MaxLevels - 1)); - int level = 0; - while (i & 1) { - i >>= 1; - level++; - } - assert(level < MaxLevels); - return level; - } + RandomLevel randomLevel{0}; // Represent a node in the SkipList. The node has multiple (i.e., level) // pointers to other nodes, and keeps a record of the max versions for each @@ -588,7 +585,7 @@ private: } void insert(const Finger &f, Version version) { - int level = randomLevel(); + int level = randomLevel.next(); // std::cout << std::string((const char*)value,length) << " level: " << // level << std::endl; Node *x = Node::create(f.value, level);