From 09bcaaa0358439aedf2f4beab53f4244b7c8d7fa Mon Sep 17 00:00:00 2001 From: JCW Date: Fri, 30 May 2025 10:04:33 +0100 Subject: [PATCH] salt based bit shift hash --- include/xrpl/beast/core/FunctionProfiler.h | 4 +- include/xrpl/beast/hash/xxhasher.h | 153 +++++++++++++++------ src/test/app/AMM_test.cpp | 19 +++ 3 files changed, 131 insertions(+), 45 deletions(-) diff --git a/include/xrpl/beast/core/FunctionProfiler.h b/include/xrpl/beast/core/FunctionProfiler.h index 81fe38630e..81b7b53b4e 100644 --- a/include/xrpl/beast/core/FunctionProfiler.h +++ b/include/xrpl/beast/core/FunctionProfiler.h @@ -9,11 +9,13 @@ #include #include #include -#include +// #include #include #include #include // std::accumulate +#define __rdtsc() 0 + namespace beast { template diff --git a/include/xrpl/beast/hash/xxhasher.h b/include/xrpl/beast/hash/xxhasher.h index 430a45b051..3da0639051 100644 --- a/include/xrpl/beast/hash/xxhasher.h +++ b/include/xrpl/beast/hash/xxhasher.h @@ -36,6 +36,9 @@ namespace beast { class xxhasher { +public: + using HashType = std::size_t; + private: // requires 64-bit std::size_t static_assert(sizeof(std::size_t) == 8, ""); @@ -58,6 +61,11 @@ private: std::size_t totalSize_ = 0; std::chrono::nanoseconds duration_{}; std::uint64_t cpuCycles = 0; + std::uint8_t seed_ = 0; + + std::array buffer_; + std::span readBuffer_; + std::span writeBuffer_; static XXH3_state_t* allocState() @@ -69,6 +77,23 @@ private: return ret; } + void + setupBuffers() + { + writeBuffer_ = std::span{buffer_}; + } + + void + writeBuffer(void const* data, std::size_t len) + { + auto bytesToWrite = std::min(len, writeBuffer_.size()); + + std::memcpy(writeBuffer_.data(), data, bytesToWrite); + writeBuffer_ = writeBuffer_.subspan(bytesToWrite); + readBuffer_ = std::span{ + std::begin(buffer_), buffer_.size() - writeBuffer_.size()}; + } + public: using result_type = std::size_t; @@ -80,38 +105,43 @@ public: xxhasher() { - auto start = std::chrono::steady_clock::now(); - auto cpuCyclesStart = __rdtsc(); - // state_ = allocState(); - // XXH3_64bits_reset(state_); - XXH3_64bits_reset(wrapper.state); - duration_ += std::chrono::steady_clock::now() - start; - cpuCycles += (__rdtsc() - cpuCyclesStart); + setupBuffers(); + // auto start = std::chrono::steady_clock::now(); + // auto cpuCyclesStart = __rdtsc(); + // // state_ = allocState(); + // // XXH3_64bits_reset(state_); + // XXH3_64bits_reset(wrapper.state); + // duration_ += std::chrono::steady_clock::now() - start; + // cpuCycles += (__rdtsc() - cpuCyclesStart); } - ~xxhasher() noexcept - { - // profiler_.functionName = "xxhasher-" + std::to_string(totalSize_); - // auto start = std::chrono::steady_clock::now(); - // if (0) - // { - // FunctionProfiler _{"-free"}; - // XXH3_freeState(state_); - // } - } + // ~xxhasher() noexcept + // { + // // profiler_.functionName = "xxhasher-" + std::to_string(totalSize_); + // // auto start = std::chrono::steady_clock::now(); + // if (0) + // { + // FunctionProfiler _{"-free"}; + // XXH3_freeState(state_); + // } + // } template < class Seed, std::enable_if_t::value>* = nullptr> explicit xxhasher(Seed seed) { - auto start = std::chrono::steady_clock::now(); - auto cpuCyclesStart = __rdtsc(); + seed_ = seed % std::numeric_limits::max(); + + setupBuffers(); + + // auto start = std::chrono::steady_clock::now(); + // auto cpuCyclesStart = __rdtsc(); // state_ = allocState(); // XXH3_64bits_reset_withSeed(state_, seed); - XXH3_64bits_reset_withSeed(wrapper.state, seed); - duration_ += std::chrono::steady_clock::now() - start; - cpuCycles += (__rdtsc() - cpuCyclesStart); + // XXH3_64bits_reset_withSeed(wrapper.state, seed); + // duration_ += std::chrono::steady_clock::now() - start; + // cpuCycles += (__rdtsc() - cpuCyclesStart); } template < @@ -119,44 +149,79 @@ public: std::enable_if_t::value>* = nullptr> xxhasher(Seed seed, Seed) { - auto start = std::chrono::steady_clock::now(); - auto cpuCyclesStart = __rdtsc(); - // state_ = allocState(); - // XXH3_64bits_reset_withSeed(state_, seed); - XXH3_64bits_reset_withSeed(wrapper.state, seed); - duration_ += std::chrono::steady_clock::now() - start; - cpuCycles += (__rdtsc() - cpuCyclesStart); + seed_ = seed % std::numeric_limits::max(); + + setupBuffers(); + // auto start = std::chrono::steady_clock::now(); + // auto cpuCyclesStart = __rdtsc(); + // // state_ = allocState(); + // // XXH3_64bits_reset_withSeed(state_, seed); + // XXH3_64bits_reset_withSeed(wrapper.state, seed); + // duration_ += std::chrono::steady_clock::now() - start; + // cpuCycles += (__rdtsc() - cpuCyclesStart); } void operator()(void const* key, std::size_t len) noexcept { + totalSize_ += len; auto start = std::chrono::steady_clock::now(); auto cpuCyclesStart = __rdtsc(); - totalSize_ += len; + // FunctionProfiler _{"-size-" + std::to_string(len)}; // XXH3_64bits_update(state_, key, len); - XXH3_64bits_update(wrapper.state, key, len); + // XXH3_64bits_update(wrapper.state, key, len); + + writeBuffer(key, len); duration_ += std::chrono::steady_clock::now() - start; cpuCycles += (__rdtsc() - cpuCyclesStart); } explicit - operator std::size_t() noexcept + operator HashType() noexcept { - auto start = std::chrono::steady_clock::now(); - // auto ret = XXH3_64bits_digest(state_); - auto ret = XXH3_64bits_digest(wrapper.state); - duration_ += std::chrono::steady_clock::now() - start; + if (readBuffer_.size() == 0) return 0; + + std::array hash{}; + const size_t bit_width = readBuffer_.size() * 8; + const size_t shift = seed_ % bit_width; - std::lock_guard lock{FunctionProfiler::mutex_}; - FunctionProfiler::funcionDurations - ["xxhasher-" + std::to_string(totalSize_)] - .time.emplace_back(duration_); - FunctionProfiler::funcionDurations - ["xxhasher-" + std::to_string(totalSize_)] - .cpuCycles.emplace_back(cpuCycles); - return ret; + for (size_t i = 0; i < 8; ++i) { + size_t out_bit_index = i * 8; + size_t in_bit_index = (out_bit_index + shift) % bit_width; + + size_t byte_index = in_bit_index / 8; + size_t bit_offset = in_bit_index % 8; + + // Grab two adjacent bytes to ensure we can extract 8 bits safely + uint8_t first = readBuffer_[byte_index % readBuffer_.size()]; + uint8_t second = readBuffer_[(byte_index + 1) % readBuffer_.size()]; + + // Combine into 16-bit buffer + uint16_t combined = (first << 8) | second; + + // Extract 8 bits starting at bit_offset + uint8_t extracted = (combined >> (8 - bit_offset)) & 0xFF; + + hash[i] = std::byte(extracted); + } + + std::uint64_t result; + std::memcpy(&result, hash.data(), hash.size()); + return result; + // auto start = std::chrono::steady_clock::now(); + // // auto ret = XXH3_64bits_digest(state_); + // auto ret = XXH3_64bits_digest(wrapper.state); + // duration_ += std::chrono::steady_clock::now() - start; + + // std::lock_guard lock{FunctionProfiler::mutex_}; + // FunctionProfiler::funcionDurations + // ["xxhasher-" + std::to_string(totalSize_)] + // .time.emplace_back(duration_); + // FunctionProfiler::funcionDurations + // ["xxhasher-" + std::to_string(totalSize_)] + // .cpuCycles.emplace_back(cpuCycles); + // return ret; } }; diff --git a/src/test/app/AMM_test.cpp b/src/test/app/AMM_test.cpp index 87988315f4..b818add909 100644 --- a/src/test/app/AMM_test.cpp +++ b/src/test/app/AMM_test.cpp @@ -37,6 +37,22 @@ #include #include +#include + +#include + +void testHasher() +{ + beast::xxhasher hasher{std::uint32_t{8}}; + + char a[] = "He"; + hasher(&a, sizeof(a)); + + auto value = static_cast(hasher); + + std::cout << value << std::endl; +} + namespace ripple { namespace test { @@ -7140,6 +7156,9 @@ private: void run() override { + testHasher(); + + return; FeatureBitset const all{jtx::supported_amendments()}; testInvalidInstance(); testInstanceCreate();