From 6b6334ce8e0d1076f44ec786a06c8ee4e2757746 Mon Sep 17 00:00:00 2001 From: Dieter Dobbelaere Date: Sun, 8 Feb 2026 15:15:59 +0100 Subject: [PATCH] Replace FNV-1a hash by faster and better MurmurHash64A. Replace FNV-1a hash algorithm by public domain MurmurHash64A, by Austin Appleby, which is faster and has better hash properties. This is also the default hash algorithm of GNU C++ Standard Library. Startup time on a given system (with x86-64-avx2 binaries) reduces from 378ms to 332ms (46ms faster). Hashing of the largest data input (46.1MB) goes from 44.2ms to 6.2ms, so about 7x faster. No functional change closes https://github.com/official-stockfish/Stockfish/pull/6579 Bench: 2570943 --- src/misc.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/misc.h | 9 +-------- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/misc.cpp b/src/misc.cpp index 3ddae503c..e0c8351fa 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -428,6 +428,45 @@ std::ostream& operator<<(std::ostream& os, SyncCout sc) { void sync_cout_start() { std::cout << IO_LOCK; } void sync_cout_end() { std::cout << IO_UNLOCK; } +// Hash function based on public domain MurmurHash64A, by Austin Appleby. +uint64_t hash_bytes(const char* data, size_t size) { + const uint64_t m = 0xc6a4a7935bd1e995ull; + const int r = 47; + + uint64_t h = size * m; + + const char* end = data + (size & ~(size_t) 7); + + for (const char* p = data; p != end; p += 8) + { + uint64_t k; + std::memcpy(&k, p, sizeof(k)); + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + } + + if (size & 7) + { + uint64_t k = 0; + for (int i = (size & 7) - 1; i >= 0; i--) + k = (k << 8) | (uint64_t) end[i]; + + h ^= k; + h *= m; + } + + h ^= h >> r; + h *= m; + h ^= h >> r; + + return h; +} + // Trampoline helper to avoid moving Logger to misc.h void start_logger(const std::string& fname) { Logger::start(fname); } diff --git a/src/misc.h b/src/misc.h index ff9d2c284..f7a2bcf2a 100644 --- a/src/misc.h +++ b/src/misc.h @@ -306,14 +306,7 @@ inline uint64_t mul_hi64(uint64_t a, uint64_t b) { #endif } -inline std::uint64_t hash_bytes(const char* data, std::size_t size) { - // FNV-1a 64-bit - const char* p = data; - std::uint64_t h = 14695981039346656037ull; - for (std::size_t i = 0; i < size; ++i) - h = (h ^ p[i]) * 1099511628211ull; - return h; -} +uint64_t hash_bytes(const char*, size_t); template inline std::size_t get_raw_data_hash(const T& value) {