From c241a8138780c0917e3aa4e20f8c799e83a110b5 Mon Sep 17 00:00:00 2001 From: helly25 <6420169+helly25@users.noreply.github.com> Date: Thu, 16 Jul 2026 20:31:15 +0100 Subject: [PATCH 1/2] Add AMD Ryzen 9 9950X 16-core processor clang-22 measurements that use -march=znver5 --- mbo/hash/README.md | 141 +++++++++++++++++- mbo/hash/hash_benchmark.cc | 14 ++ ...-16-core-processor_clang-22_latency128.svg | 50 +++++++ ...x-16-core-processor_clang-22_latency64.svg | 75 ++++++++++ ...processor_clang-22_throughput128_Short.svg | 27 ++++ ...e-processor_clang-22_throughput128_Web.svg | 34 +++++ ...-processor_clang-22_throughput64_Short.svg | 44 ++++++ ...re-processor_clang-22_throughput64_Web.svg | 53 +++++++ ..._10c_clang-22_29b54ccd_20260716_194643.tgz | 3 + ...or_10c_gcc-15_80a4c8a8_20260714_225122.tgz | 3 - ..._18c_clang-21_80a4c8a8_20260714_233133.tgz | 3 - .../measurements/hash_benchmark_report.py | 28 +++- 12 files changed, 456 insertions(+), 19 deletions(-) create mode 100644 mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency128.svg create mode 100644 mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency64.svg create mode 100644 mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Short.svg create mode 100644 mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Web.svg create mode 100644 mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Short.svg create mode 100644 mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Web.svg create mode 100644 mbo/hash/measurements/data/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_10c_clang-22_29b54ccd_20260716_194643.tgz delete mode 100644 mbo/hash/measurements/data/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_10c_gcc-15_80a4c8a8_20260714_225122.tgz delete mode 100644 mbo/hash/measurements/data/macos-arm64-apple-m5-pro_18c_clang-21_80a4c8a8_20260714_233133.tgz diff --git a/mbo/hash/README.md b/mbo/hash/README.md index dee2263..91d550c 100644 --- a/mbo/hash/README.md +++ b/mbo/hash/README.md @@ -306,7 +306,133 @@ Everything between the markers is generated per machine by `publish` from the committed bundles - regenerate it, don't hand-edit: - + + +### AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd + + + +![mbo/hash 64-bit latency, AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd](measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency64.svg) + +#### 64-bit latency (ns/hash at exact length, mean of the 3 best of 9 reps; lower is better) + +| Length | mumbo | rapidhash | xxh3 | xxh64 | murmur3 | siphash24 | fnv1a | dumbo | +| -----: | -------: | --------: | ----: | ----: | ------: | --------: | -------: | -------: | +| 1 B | 1.33 | 1.48 | 1.70 | 2.01 | 3.06 | 7.94 | **0.39** | 1.25 | +| 3 B | 1.47 | 1.48 | 1.70 | 2.43 | 3.07 | 7.94 | **0.81** | 1.65 | +| 5 B | 1.28 | 1.47 | 1.65 | 2.54 | 2.20 | 5.05 | **1.17** | 1.22 | +| 7 B | 1.29 | 1.47 | 1.65 | 2.91 | 2.20 | 5.05 | 1.61 | **1.22** | +| 8 B | 1.28 | 1.47 | 1.64 | 2.19 | 2.20 | 6.02 | 1.27 | **1.22** | +| 11 B | **1.25** | 1.47 | 1.55 | 3.25 | 13.70 | 10.65 | 2.07 | 2.16 | +| 15 B | **1.24** | 1.47 | 1.55 | 3.63 | 2.58 | 6.14 | 3.25 | 1.79 | +| 16 B | **1.25** | 1.47 | 1.55 | 2.59 | 2.87 | 7.74 | 3.16 | 1.79 | +| 19 B | 1.75 | **1.66** | 1.92 | 3.92 | 14.41 | 10.94 | 4.28 | 2.48 | +| 22 B | 1.75 | **1.66** | 1.92 | 3.99 | 3.49 | 7.72 | 5.37 | 2.11 | +| 27 B | 1.76 | **1.66** | 1.92 | 4.36 | 4.64 | 11.36 | 6.88 | 2.88 | +| 32 B | 1.76 | **1.66** | 1.92 | 4.34 | 4.09 | 10.94 | 8.88 | 2.51 | +| 38 B | 2.11 | **1.95** | 2.82 | 5.89 | 4.58 | 10.95 | 11.61 | 3.06 | +| 47 B | 2.11 | **1.94** | 2.82 | 7.17 | 5.14 | 12.46 | 15.76 | 3.51 | +| 48 B | 2.11 | **1.94** | 2.82 | 5.83 | 5.15 | 14.16 | 15.70 | 3.51 | +| 63 B | 2.47 | **2.25** | 2.82 | 8.98 | 6.33 | 15.64 | 24.43 | 4.52 | +| 64 B | 2.47 | **2.25** | 2.82 | 5.32 | 6.47 | 17.36 | 24.63 | 4.50 | +| 127 B | 4.84 | **3.61** | 4.64 | 11.53 | 11.24 | 28.61 | 66.37 | 8.65 | +| 128 B | 5.40 | **3.61** | 4.59 | 7.12 | 11.49 | 30.21 | 66.38 | 8.65 | +| 256 B | 8.80 | **5.88** | 28.75 | 11.18 | 20.99 | 55.92 | 156.8 | 19.97 | +| 1 KiB | 35.85 | **17.15** | 40.67 | 34.89 | 80.08 | 210.0 | 703.3 | 104.9 | +| 4 KiB | 160.1 | **64.56** | 124.2 | 131.1 | 316.3 | 828.6 | 2885 | 471.4 | + +![mbo/hash 64-bit throughput (Short), AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd](measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Short.svg) + +#### 64-bit throughput, Short lengths (GiB/s over lengths <= max, mean of the 3 best of 9 reps; higher is better) + +| max len | mumbo | rapidhash | xxh3 | xxh64 | murmur3 | siphash24 | fnv1a | dumbo | +| ------: | -------: | --------: | ---: | ----: | ------: | --------: | -------: | ----: | +| 8 B | 2.28 | 1.11 | 1.94 | 1.21 | 1.27 | 0.55 | **2.43** | 2.16 | +| 12 B | **4.29** | 3.64 | 3.54 | 2.07 | 2.04 | 0.83 | 2.88 | 3.10 | +| 16 B | **6.24** | 5.11 | 5.14 | 2.81 | 2.86 | 1.26 | 3.05 | 4.31 | +| 23 B | **7.04** | 6.60 | 6.33 | 3.45 | 3.35 | 1.54 | 2.99 | 5.17 | +| 31 B | **8.32** | 8.12 | 7.66 | 4.05 | 3.96 | 1.81 | 3.01 | 6.05 | +| 38 B | **8.20** | 8.02 | 7.46 | 3.96 | 3.88 | 1.78 | 2.87 | 5.96 | +| 53 B | **9.07** | 8.90 | 8.20 | 4.27 | 4.23 | 1.92 | 2.83 | 6.45 | +| 80 B | **9.07** | 8.91 | 8.19 | 4.32 | 4.24 | 1.92 | 2.79 | 6.45 | +| 128 B | **9.05** | 8.90 | 8.18 | 4.32 | 4.22 | 1.91 | 2.80 | 6.43 | + +![mbo/hash 64-bit throughput (Web), AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd](measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Web.svg) + +#### 64-bit throughput, Web lengths (GiB/s over lengths <= max, mean of the 3 best of 9 reps; higher is better) + +| max len | mumbo | rapidhash | xxh3 | xxh64 | murmur3 | siphash24 | fnv1a | dumbo | +| ------: | -------: | --------: | ---: | ----: | ------: | --------: | ----: | ----: | +| 15 B | **4.86** | 4.16 | 4.03 | 2.33 | 2.37 | 1.02 | 3.05 | 3.69 | +| 28 B | 7.34 | **7.62** | 6.98 | 3.85 | 3.62 | 1.63 | 2.86 | 5.66 | +| 45 B | 11.4 | **11.9** | 9.99 | 5.05 | 5.16 | 2.32 | 2.70 | 7.84 | +| 75 B | 14.5 | **15.2** | 12.7 | 6.10 | 6.22 | 2.76 | 2.42 | 9.26 | +| 120 B | 16.2 | **17.5** | 14.7 | 7.14 | 6.90 | 3.02 | 2.14 | 9.73 | +| 220 B | 16.7 | **19.0** | 15.3 | 7.80 | 7.39 | 3.20 | 2.03 | 9.95 | +| 512 B | 17.1 | **20.5** | 14.3 | 8.57 | 7.73 | 3.30 | 1.89 | 9.63 | +| 2 KiB | 18.4 | **23.7** | 15.1 | 10.1 | 8.33 | 3.52 | 1.73 | 9.31 | +| 4 KiB | 18.2 | **23.2** | 14.7 | 9.93 | 8.25 | 3.47 | 1.73 | 9.26 | + +![mbo/hash 128-bit latency, AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd](measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency128.svg) + +#### 128-bit latency (ns/hash at exact length, mean of the 3 best of 9 reps; native-128 only; lower is better) + +| Length | jumbo | xxh3 | murmur3 | +| -----: | --------: | -------: | ------: | +| 1 B | **2.23** | 2.34 | 3.07 | +| 3 B | 2.73 | **2.34** | 3.07 | +| 5 B | 2.37 | **1.96** | 2.16 | +| 7 B | 2.37 | **1.96** | 2.15 | +| 8 B | 2.18 | **1.96** | 2.16 | +| 11 B | **2.15** | 2.34 | 13.73 | +| 15 B | **2.15** | 2.34 | 2.63 | +| 16 B | **2.15** | 2.34 | 2.95 | +| 19 B | **2.66** | 2.94 | 14.33 | +| 22 B | **2.66** | 2.94 | 3.54 | +| 27 B | **2.66** | 2.94 | 4.66 | +| 32 B | **2.66** | 2.94 | 4.13 | +| 38 B | **3.22** | 3.83 | 4.65 | +| 47 B | **3.21** | 3.84 | 5.18 | +| 48 B | **3.21** | 3.84 | 5.21 | +| 63 B | **3.83** | 3.86 | 6.39 | +| 64 B | 4.36 | **3.84** | 6.53 | +| 127 B | 6.07 | **5.84** | 11.26 | +| 128 B | **5.26** | 5.78 | 11.53 | +| 256 B | **7.23** | 25.79 | 21.04 | +| 1 KiB | **20.86** | 37.90 | 80.09 | +| 4 KiB | **77.54** | 119.9 | 316.4 | + +![mbo/hash 128-bit throughput (Short), AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd](measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Short.svg) + +#### 128-bit throughput, Short lengths (GiB/s over lengths <= max, mean of the 3 best of 9 reps; higher is better) + +| max len | jumbo | xxh3 | murmur3 | +| ------: | -------: | -------: | ------: | +| 8 B | 1.46 | **1.56** | 1.25 | +| 12 B | **2.62** | 2.59 | 2.02 | +| 16 B | **3.75** | 3.58 | 2.83 | +| 23 B | **4.60** | 4.33 | 3.32 | +| 31 B | **5.55** | 5.19 | 3.92 | +| 38 B | **5.47** | 5.10 | 3.84 | +| 53 B | **6.05** | 5.64 | 4.19 | +| 80 B | **6.05** | 5.63 | 4.20 | +| 128 B | **6.04** | 5.62 | 4.17 | + +![mbo/hash 128-bit throughput (Web), AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd](measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Web.svg) + +#### 128-bit throughput, Web lengths (GiB/s over lengths <= max, mean of the 3 best of 9 reps; higher is better) + +| max len | jumbo | xxh3 | murmur3 | +| ------: | -------: | ---: | ------: | +| 15 B | **2.97** | 2.96 | 2.35 | +| 28 B | **5.08** | 4.81 | 3.59 | +| 45 B | **7.84** | 7.06 | 5.11 | +| 75 B | **9.93** | 9.11 | 6.17 | +| 120 B | **11.5** | 10.8 | 6.83 | +| 220 B | **12.7** | 11.7 | 7.31 | +| 512 B | **14.1** | 11.5 | 7.66 | +| 2 KiB | **16.6** | 12.8 | 8.28 | +| 4 KiB | **16.2** | 12.4 | 8.18 | ### AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · gcc-15 · 29b54ccd @@ -623,11 +749,14 @@ Reading the results: be; `murmur3` (2011) fails the modern battery broadly; and `fnv1a` - the algorithm family behind many `std::hash` implementations - passes 7 of 186 tests. Numbers worth remembering when defaulting to `std::hash`. -- The mumbo/jumbo family is the default in all forms; the extras remain - available for - canonical-value interop via `hash_extra.h` (`//mbo/hash:hash_extra_cc`, - which carries the third-party NOTICE obligations - see the repository-root - NOTICE). +- When build with `-march=znsver5` to enable `AVX-512` and any other instruction + that may optimize the code on an AMD ZEN 5 CPU, the `mumbo/jumbo` and `dumbo` + family actually performs incredibly well as can be seen in the first report + set which was measured with `--config=clang` `--copt=-march=znver5`. +- The `mumbo/jumbo` family is thus the default in all forms. The extras remain + available for canonical-value interop via `hash_extra.h` found in library + target `//mbo/hash:hash_extra_cc`. That target carries the third-party + [NOTICE](../../NOTICE). ### mumbo: the measured design iterations diff --git a/mbo/hash/hash_benchmark.cc b/mbo/hash/hash_benchmark.cc index a178068..6dd4670 100644 --- a/mbo/hash/hash_benchmark.cc +++ b/mbo/hash/hash_benchmark.cc @@ -22,6 +22,11 @@ // every dispatch-tier boundary and SSO cutoff, for the complete dataset and // the ns-vs-length graph. +#ifdef __linux__ +# include +# include +#endif // __linux__ + #include #include #include @@ -377,6 +382,15 @@ void RegisterAll(std::tuple /*algorithms*/) { } // namespace mbo::hash int main(int argc, char** argv) { + benchmark::MaybeReenterWithoutASLR(argc, argv); // NO ASLR + +#ifdef __linux__ + cpu_set_t set; + CPU_ZERO(&set); + CPU_SET(0, &set); // Pin to the first available core + pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &set); +#endif // __linux__ + mbo::hash::RegisterAll(mbo::hash::algo::AllAlgorithms{}); benchmark::Initialize(&argc, argv); // The build compiler is a first-class axis of a measurement (GCC vs Clang perf diff --git a/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency128.svg b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency128.svg new file mode 100644 index 0000000..b5c2749 --- /dev/null +++ b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency128.svg @@ -0,0 +1,50 @@ + + +mbo/hash - 128-bit latency +AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd + +2 + +5 + +10 + +20 + +50 + +100 + +200 + +1 B + + +4 B + + +16 B + + +64 B + + +256 B + + +1 KiB + + +4 KiB +key length (log scale) +ns / op (log scale) + + +jumbo + + +xxh3 + + +murmur3 + diff --git a/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency64.svg b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency64.svg new file mode 100644 index 0000000..f271ac6 --- /dev/null +++ b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_latency64.svg @@ -0,0 +1,75 @@ + + +mbo/hash - 64-bit latency +AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd + +0.5 + +1 + +2 + +5 + +10 + +20 + +50 + +100 + +200 + +500 + +1000 + +2000 + +1 B + + +4 B + + +16 B + + +64 B + + +256 B + + +1 KiB + + +4 KiB +key length (log scale) +ns / op (log scale) + + +mumbo + + +rapidhash + + +xxh3 + + +xxh64 + + +murmur3 + + +siphash24 + + +fnv1a + + +dumbo + diff --git a/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Short.svg b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Short.svg new file mode 100644 index 0000000..8117da8 --- /dev/null +++ b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Short.svg @@ -0,0 +1,27 @@ + + +mbo/hash - 128-bit throughput (Short) +AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd + +2 + +5 + + +16 B + + +64 B + +max length (log scale) +GiB / s (log scale) + + +jumbo + + +xxh3 + + +murmur3 + diff --git a/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Web.svg b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Web.svg new file mode 100644 index 0000000..aca4b98 --- /dev/null +++ b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput128_Web.svg @@ -0,0 +1,34 @@ + + +mbo/hash - 128-bit throughput (Web) +AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd + +5 + +10 + +16 B + + +64 B + + +256 B + + +1 KiB + + +4 KiB +max length (log scale) +GiB / s (log scale) + + +jumbo + + +xxh3 + + +murmur3 + diff --git a/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Short.svg b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Short.svg new file mode 100644 index 0000000..435798e --- /dev/null +++ b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Short.svg @@ -0,0 +1,44 @@ + + +mbo/hash - 64-bit throughput (Short) +AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd + +1 + +2 + +5 + + +16 B + + +64 B + +max length (log scale) +GiB / s (log scale) + + +mumbo + + +rapidhash + + +xxh3 + + +xxh64 + + +murmur3 + + +siphash24 + + +fnv1a + + +dumbo + diff --git a/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Web.svg b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Web.svg new file mode 100644 index 0000000..6b64809 --- /dev/null +++ b/mbo/hash/measurements/charts/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_clang-22_throughput64_Web.svg @@ -0,0 +1,53 @@ + + +mbo/hash - 64-bit throughput (Web) +AMD Ryzen 9 9950X 16-Core Processor · Linux · x86_64 · 10-core · clang-22 · 29b54ccd + +2 + +5 + +10 + +20 + +16 B + + +64 B + + +256 B + + +1 KiB + + +4 KiB +max length (log scale) +GiB / s (log scale) + + +mumbo + + +rapidhash + + +xxh3 + + +xxh64 + + +murmur3 + + +siphash24 + + +fnv1a + + +dumbo + diff --git a/mbo/hash/measurements/data/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_10c_clang-22_29b54ccd_20260716_194643.tgz b/mbo/hash/measurements/data/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_10c_clang-22_29b54ccd_20260716_194643.tgz new file mode 100644 index 0000000..42e32c5 --- /dev/null +++ b/mbo/hash/measurements/data/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_10c_clang-22_29b54ccd_20260716_194643.tgz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81754d0b63f56a148156cc956caaa2e14693e42f3734b9cec93a380225e21b06 +size 1937516 diff --git a/mbo/hash/measurements/data/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_10c_gcc-15_80a4c8a8_20260714_225122.tgz b/mbo/hash/measurements/data/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_10c_gcc-15_80a4c8a8_20260714_225122.tgz deleted file mode 100644 index b47f3ba..0000000 --- a/mbo/hash/measurements/data/linux-x86-64-amd-ryzen-9-9950x-16-core-processor_10c_gcc-15_80a4c8a8_20260714_225122.tgz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c20454c6699c04ddd482c69b75896daf29b345986908c101ab8f8438105cba78 -size 1288521 diff --git a/mbo/hash/measurements/data/macos-arm64-apple-m5-pro_18c_clang-21_80a4c8a8_20260714_233133.tgz b/mbo/hash/measurements/data/macos-arm64-apple-m5-pro_18c_clang-21_80a4c8a8_20260714_233133.tgz deleted file mode 100644 index 1b54525..0000000 --- a/mbo/hash/measurements/data/macos-arm64-apple-m5-pro_18c_clang-21_80a4c8a8_20260714_233133.tgz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4819f142e2117870849e22441627a21e9f68721f7ce16e9c39448b48ba5eb73 -size 689950 diff --git a/mbo/hash/measurements/hash_benchmark_report.py b/mbo/hash/measurements/hash_benchmark_report.py index 494c963..fd3e048 100755 --- a/mbo/hash/measurements/hash_benchmark_report.py +++ b/mbo/hash/measurements/hash_benchmark_report.py @@ -186,7 +186,11 @@ def _machine_augment(): return augment -def _run_benchmark(mode, reps, min_time, warmup, config=None): +def _expand_list_arg(prefix, args): + return [f"{prefix}={arg}" for arg in args] if args else [] + + +def _run_benchmark(mode, reps, min_time, warmup, config=None, copt=None, host_copt=None): """Runs the bazel benchmark with the measurement precautions; returns parsed JSON. `config` selects a bazel `--config` (e.g. 'clang' / 'gcc'), so the toolchain - @@ -198,20 +202,28 @@ def _run_benchmark(mode, reps, min_time, warmup, config=None): cmd = [ "bazel", "run", + "--color=yes", "-c", "opt", - *([f"--config={config}"] if config else []), + *_expand_list_arg("--config", config), + *_expand_list_arg("--copt", copt), + *_expand_list_arg("--host_copt", host_copt), _BENCHMARK_TARGET, "--", - "--benchmark_format=json", + "--benchmark_out_format=json", + "--benchmark_out=/tmp/results.json", + "--benchmark_format=console", f"--benchmark_repetitions={reps}", f"--benchmark_min_time={min_time}s", f"--benchmark_min_warmup_time={warmup}s", "--benchmark_enable_random_interleaving=true", + "--benchmark_display_aggregates_only=true", ] print(f"$ MBO_HASH_BENCHMARK_FULL={env.get('MBO_HASH_BENCHMARK_FULL', '')} {' '.join(cmd)}", file=sys.stderr) - out = subprocess.run(cmd, capture_output=True, text=True, check=True, env=env).stdout - return json.loads(out[out.index("{") :]) + subprocess.run(cmd, text=True, check=True, env=env) + with open("/tmp/results.json", "rb") as f: + out = f.read() + return json.loads(out) def _distill_buckets(raw): @@ -1101,7 +1113,9 @@ def main(argv): p_run.add_argument("--raw", help="write google/benchmark raw JSON here (.gz compresses)") p_run.add_argument("--out", help="write the distilled canonical results JSON here") p_run.add_argument("--tables", action="store_true") - p_run.add_argument("--config", help="bazel --config for the benchmark build (e.g. clang, gcc); picks the toolchain and the recorded compiler") + p_run.add_argument("--config", action="append", default=[], help="bazel --config for the benchmark build (e.g. `--config=clang`); works well with .user.bazelrc to pick the toolchain and the recorded compiler") + p_run.add_argument("--copt", action="append", default=[], help="bazel --copt for the benchmark build (e.g. `--copt=-O3`); allows manual fine tuning of the compiler flags") + p_run.add_argument("--host_copt", action="append", default=[], help="bazel --host_copt for the benchmark build (e.g. `--host_copt=-O3`); allows manual fine tuning of the host compiler flags") p_store = sub.add_parser("store", help="distill raw benchmark JSON to canonical results JSON") p_store.add_argument("--raw", required=True) @@ -1187,7 +1201,7 @@ def main(argv): return 0 if args.command == "run": - raw = _run_benchmark(args.mode, args.reps, args.min_time, args.warmup, args.config) + raw = _run_benchmark(args.mode, args.reps, args.min_time, args.warmup, args.config, args.copt, args.host_copt) if args.raw: raw_path = _timestamped(args.raw, stamp) opener = gzip.open if raw_path.endswith(".gz") else open From 0ae2c23cf216bdeb39ecf8d3bb3666499875a6d2 Mon Sep 17 00:00:00 2001 From: helly25 <6420169+helly25@users.noreply.github.com> Date: Thu, 16 Jul 2026 21:03:05 +0100 Subject: [PATCH 2/2] Re-add --- mbo/diff/README.md | 159 ++++++++++++++++++++++++++++++++++++++++++ mbo/hash/README.md | 167 ++++++++++++++++++++++++--------------------- 2 files changed, 248 insertions(+), 78 deletions(-) create mode 100644 mbo/diff/README.md diff --git a/mbo/diff/README.md b/mbo/diff/README.md new file mode 100644 index 0000000..d1bd83b --- /dev/null +++ b/mbo/diff/README.md @@ -0,0 +1,159 @@ +# mbo/diff: Unified-Diffing Utilities + +Part of the **MBO** library ecosystem, `mbo/diff` provides lightweight utilities for generating unified diffs, a standalone command-line diffing tool, and Bazel macros designed for integration testing against golden files. + +## 1. C++ API Reference: `mbo::diff::Diff` + +The C++ library resides under the namespace `mbo::diff`. It is built to leverage C++20 features (such as `std::string_view` and `std::span`) and integrates natively with Google's Abseil library. + +### `DiffOptions` Struct + +The behavior of the diff engine and formatting output is fully controlled via the `mbo::diff::DiffOptions` struct: + +| Field Name | Type | Default | Description | +| :----------------------- | :------------- | :-------------------- | :--------------------------------------------------------------------------------------------------- | +| `unified_lines` | `size_t` | `3` | The number of context lines to display above and below each diff hunk. | +| `ignore_case` | `bool` | `false` | If `true`, performs a case-insensitive comparison of lines. | +| `ignore_spaces` | `IgnoreSpaces` | `IgnoreSpaces::kNone` | Controls how whitespace is treated. See [Whitespace Configuration](#whitespace-configuration) below. | +| `ignore_blank_lines` | `bool` | `false` | If `true`, runs of empty or whitespace-only lines that are added or removed are ignored. | +| `normalize_line_endings` | `bool` | `true` | Standardizes `\r\n` (Windows) and `\n` (Unix) line endings to `\n` before computing the diff. | + +#### Whitespace Configuration + +The `IgnoreSpaces`: + +- **`IgnoreSpaces::kNone`**: Strict match. Every whitespace character is treated as significant. +- **`IgnoreSpaces::kTrailing`**: Ignores trailing whitespace at the end of each line. +- **`IgnoreSpaces::kChange`**: Ignores changes in the _amount_ of whitespace (e.g., multiple spaces or tabs are treated as a single space), but requires at least some whitespace if it acts as a delimiter. +- **`IgnoreSpaces::kAll`**: Completely ignores all whitespace characters during the comparison. + +### Basic C++ Usage + +```cpp +#include "mbo/diff/diff.h" +#include "absl/status/statusor.h" +#include +#include + +int main() { + std::string_view original = "Line 1\nLine 2\n\nLine 3\n"; + std::string_view modified = "line 1\nLine 2 changed\nLine 3\n"; + + // Configure high-precision diff rules + mbo::diff::DiffOptions options; + options.unified_lines = 2; + options.ignore_case = true; + options.ignore_blank_lines = true; + options.ignore_spaces = mbo::diff::IgnoreSpaces::kTrailing; + + absl::StatusOr diff_output = mbo::diff::Diff::FormatUnified( + "src/original.txt", original, + "src/modified.txt", modified, + options + ); + + if (diff_output.ok()) { + if (diff_output->empty()) { + std::cout << "Files are identical under the current configuration." << std::endl; + } else { + std::cout << *diff_output << std::endl; + } + } else { + std::cerr << "Diff failed to execute: " << diff_output.status().message() << std::endl; + } + + return 0; +} + +``` + +## 2. Command-Line Tool Reference: `unified_diff` + +The `unified_diff` binary exposes the underlying C++ diffing configurations via standard command-line flags. + +### CLI Parameters & Flags + +| Flag | Long Option | Type | Default | Description | +| ---- | ------------------------- | ------ | ------- | ------------------------------------------------- | +| `-u` | `--unified` | `int` | `3` | Number of context lines to output around changes. | +| `-i` | `--ignore-case` | `bool` | `false` | Ignore case differences in file contents. | +| `-w` | `--ignore-all-space` | `bool` | `false` | Ignore all white space when comparing lines. | +| `-b` | `--ignore-space-change` | `bool` | `false` | Ignore changes in amount of white space. | +| `-B` | `--ignore-blank-lines` | `bool` | `false` | Ignore changes whose lines are all blank. | +| `-Z` | `--ignore-trailing-space` | `bool` | `false` | Ignore white space at line end. | +| | `--strip-trailing-cr` | `bool` | `true` | Strip carriage return (`\r`) at the end of lines. | + +### CLI Compilation & Usage + +Build the tool with Bazel: + +```bash +bazel build //mbo/diff:unified_diff + +``` + +Perform a custom, whitespace-insensitive diff with 5 context lines: + +```bash +./bazel-bin/mbo/diff/unified_diff \ + --unified=5 \ + --ignore-space-change \ + --ignore-blank-lines \ + path/to/original.txt path/to/modified.txt + +``` + +## 3. Bazel Integration: `diff_test` Macro + +The `diff_test` Bazel macro (loaded from `@mbo//mbo/diff:diff.bzl`) acts as a wrapper around the `unified_diff` binary, running comparisons as part of your standard Bazel test suite. + +### Macro Arguments Reference + +When declaring a `diff_test` target in your `BUILD` file, the following arguments are available: + +| Argument | Type | Required | Description | +| --------------------- | ----------------- | --------------------- | ----------------------------------------------------------------------- | +| `name` | `string` | **Yes** | A unique name for this test target. | +| `file_a` | `label` | **Yes** | The first file to compare (often a generated file/target output). | +| `file_b` | `label` | **Yes** | The second file to compare (often your expected "golden" file). | +| `unified` | `int` | No (Default: `3`) | The number of context lines to display on match failure. | +| `ignore_case` | `bool` | No (Default: `false`) | If `true`, enables case-insensitive comparison. | +| `ignore_space_change` | `bool` | No (Default: `false`) | Ignores changes in whitespace spacing amount. | +| `ignore_blank_lines` | `bool` | No (Default: `false`) | Ignores runs of empty lines. | +| `args` | `list of strings` | No | Extra command-line arguments to pass directly to the underlying binary. | +| `data` | `list of labels` | No | Additional runfiles required by the test. | + +### Advanced `BUILD` Example + +This configuration dynamically generates an output file, then uses `diff_test` with custom matching rules to ignore formatting differences: + +```bazel +load("@mbo//mbo/diff:diff.bzl", "diff_test") + +# Generate some configuration or build output +genrule( + name = "generate_config", + srcs = ["template.conf"], + outs = ["generated.conf"], + cmd = "$(location //tools:config_builder) --input=$< --output=$@", + tools = ["//tools:config_builder"], +) + +# Perform strict comparison but ignore minor whitespace styling and blank lines +diff_test( + name = "verify_config_generation", + file_a = ":generated.conf", + file_b = "//testdata:golden_config.conf", + ignore_space_change = True, + ignore_blank_lines = True, + unified = 5, +) + +``` + +Run the validation test with: + +```bash +bazel test //path/to/package:verify_config_generation + +``` diff --git a/mbo/hash/README.md b/mbo/hash/README.md index 91d550c..a97f919 100644 --- a/mbo/hash/README.md +++ b/mbo/hash/README.md @@ -1,25 +1,27 @@ # mbo/hash - fast, constexpr-safe, non-cryptographic hashing -Fast, constexpr-safe, non-cryptographic hashing, built around the in-house +Fast, `constexpr`-safe, non-cryptographic hashing, built around the in-house **mumbo/jumbo and dumbo** family: notice-free, pure Apache-2.0, and MUM-based -(widening multiply). All three pass [SMHasher3](https://gitlab.com/fwojcik/smhasher3) -clean (188/188). `mumbo` (64-bit) is the all-round default: among the fastest -hashes here on every machine we measured, SMHasher3-clean, notice-free Apache-2.0, -and with both streaming and a Starlark port - few alternatives combine all of -these. Its native 128-bit sibling `jumbo` is the only clean native 128 we -measured and an excellent 128-bit choice. `dumbo` is a compact single-lane -companion with a very different profile - fastest here on tiny keys, slower on -bulk - that trades reach for size, not quality. - -It also ships a **build-seed mangle** (`hash_mangle.h`): restricted/limited, -constexpr-safe compile-time hash mangling with release-time rotation enforcement. -That is hash randomization for the constexpr world, which compile-time hashing -otherwise rules out. +(widening multiply). All three algorithm cleanly pass the quality assesment of +[SMHasher3](https://gitlab.com/fwojcik/smhasher3) with a rating of 188/188. + +The `mumbo` algorithm (64-bit) is the all-round default of this library. It is +among the fastest hashes offered in the lirbrary on every machine we measured. +Is is SMHasher3-clean, notice-free Apache-2.0 licensed, and offers both a +streaming API and a [Starlark](https://github.com/bazelbuild/starlark) port so +you can natively use the algorithm in [Bazel](https://bazel.build/) projects. +Its native 128-bit sibling `jumbo` is the only clean native 128 we measured. +Last but not least `dumbo` is a compact single-lane companion with a very a +different profile - fastest (here) on tiny keys, slower on bulk, but still +passing SMHasher2 and thus offering fully prooven hash algorithm quality. + +This sub-library also ships a **build-seed mangle** (`hash_mangle.h`) wrapper +which offers restricted/limited, `constexpr`-safe compile-time hash mangling +with release-time rotation enforcement. That is hash randomization for the +`constexpr` world, which compile-time hashing otherwise rules out. The third-party algorithms (rapidhash, xxh3/xxh64, murmur3, siphash, fnv1a) are -exact transcriptions, kept for interop and comparison. Algorithm reference and -API listing: see the [repository README](../../README.md). Last but not least we -provide quality (SMHasher3) and performance measurements for all algorithms below. +exact transcriptions. They are provided for interoperability and comparison. ## Offerings @@ -27,90 +29,99 @@ Three entry points, split by contract: - **`hash.h` / `:hash_cc` - deterministic hashing.** `GetHash64` / `GetHash128` / `GetHash32`, the `Hasher` container functor, and - `Streamer` incremental hashing - all constexpr-safe and fully - reproducible for a given library version. Use for hash tables (heterogeneous - string lookup), tokenization/interning, compile-time hashing + `Streamer` incremental hashing - all `constexpr`-safe and fully + reproducible for a given library version. Designer for use in hash tables + (heterogeneous string lookup), tokenization/interning, compile-time hashing (`static_assert`, switch-on-hash), and cross-process consistency within one - build. Values are not a persistence or wire format. + build. Values are not appropriate as a persistence mechanism or wire format. - **`hash_mangle.h` / `:hash_mangle_cc` - deliberately unstable hashing.** `GetHash` / `MangledHasher`: `GetHash64` XORed with one build-selected constant, so values do not compare across independently configured builds. - Use when hash values must not quietly become load-bearing (persisted tables, - golden values, cross-build protocols) - the instability is the feature. - Still constexpr; semantics and design rationale in the build-seed mangle - section, the flags in the Configuration section below. -- **`hash_extra.h` / `:hash_extra_cc` - NOTICE-bearing algorithms.** Canonical - rapidhash, xxh3, and xxh64 transcriptions, for interop with externally - defined values and for comparison. Shipping a binary that links this target - requires shipping the repository-root [NOTICE](../../NOTICE). + Use when hash values must not become a dependency (persisted tables, golden + values, cross-build protocols) - the instability is the feature. While this is + all still `constexpr` read up on semantics and design rationale in the below + section on the build-seed mangling. +- **`hash_extra.h` / `:hash_extra_cc` - NOTICE-brequiring algorithms.** These + canonical algorithms (rapidhash, xxh3, and xxh64) are completely verified and + ested transcriptions, for interoperability with externally defined values and + for comparison. Shipping a binary that links this target requires shipping the + repository-root [NOTICE](../../NOTICE). ## Principles - **Canonical or honest**: third-party algorithms (rapidhash, XXH64/XXH3, MurmurHash3, SipHash, FNV-1a) are transcriptions producing the exact published reference values on every platform, pinned by reference vectors - and differential tests against the reference libraries. The in-house `mumbo` - algorithm is documented with its measured quality and performance data - (below) and its design iterations. + and differential tests against the reference libraries. The in-house `mumbo` / + `jumbo` and `dumbo` family of algorithms is documented with its measured + quality and performance data (below) and its design iterations. - **constexpr-safe single path**: compile-time and run-time evaluation always agree; streaming (where provided) equals the one-shot value by contract. - **Apache-2.0 with clean attribution**: transcription notices live in the repository-root [NOTICE](../../NOTICE); [LICENSE](../../LICENSE) stays pure - Apache-2.0. No crypto-library - dependencies - digests and hashes are spec-frozen pure functions that we + Apache-2.0 and are free of crypto-library dependencies. All hash algorithms + (and similarily all digest algorithms) are spec-frozen pure functions that we verify against official vectors instead of trusting an unverifiable supply - chain (see [mbo/digest/README.md](../digest/README.md) for the full argument). + chain (also see [mbo/digest/README.md](../digest/README.md)). - **Non-cryptographic hash-table hashes, with one keyed exception**: the defaults and comparison algorithms are fast hashes for hash tables and - interning - their values are neither stable across versions nor safe against - adversaries. `siphash` is the deliberate exception, a keyed PRF included as - the hash-flooding-resistant choice when the seed is a secret; it is still a - hash-table hash (`GetHash64` / `Hasher`), not a message digest. Cryptographic - **message digests** and MACs (SHA-2/3, MD5 interop, BLAKE2/3, HMAC) are a - different contract and live in [mbo/digest](../digest/README.md). + interning. Their values are neither stable across versions nor safe against + adversaries. The one deliberate exceptions is `siphash`, a keyed PRF + ([Pseudo Random Function](https://en.wikipedia.org/wiki/Pseudorandom_function_family)) + included as the hash-flooding-resistant choice when the seed is a secret. It + is still a hash-table hash (`GetHash64` / `Hasher`), not a message digest. +- **message digests**: Non-cryptographic Digest and MACs (SHA-2/3, MD5 interop, + BLAKE2/3, HMAC) are a different contract and live in [mbo/digest](../digest/README.md). ## Algorithm overview -This is the at-a-glance map; the `SMHasher3` column is a PASS/FAIL summary only. +This is the at-a-glance overview- map. The `SMHasher3` column is a PASS/FAIL summary only. For the exact score and the failing families see [Quality: SMHasher3](#quality-smhasher3). -| Algorithm | Bits | Available via | Starlark | NOTICE | Seeded | Streaming | SMHasher3 | -| ----------- | ---: | --------------------------------- | -------- | ----------------------- | ------ | --------- | --------- | -| `mumbo` | 64 | `hash.h` (default 64/32) | yes | none (in-house) | yes | yes | PASS | -| `jumbo` | 128 | `hash.h` (default 128) | no | none (in-house) | yes | yes (64) | PASS | -| `murmur3` | 128 | `hash.h` | no | none (public domain) | yes | no | FAIL | -| `siphash` | 64 | `hash.h` | no | none (CC0) | keyed | yes | PASS | -| `fnv1a` | 64 | `hash.h` | yes | none (public domain) | yes | no | FAIL | -| `dumbo` | 64 | `hash.h` | yes | none (in-house) | yes | no | PASS | -| `rapidhash` | 64 | `hash_extra.h` + `:hash_extra_cc` | no | **MIT - ship NOTICE** | yes | no | PASS | -| `xxh64` | 64 | `hash_extra.h` + `:hash_extra_cc` | no | **BSD-2 - ship NOTICE** | yes | yes | FAIL | -| `xxh3` | 64 | `hash_extra.h` + `:hash_extra_cc` | no | **BSD-2 - ship NOTICE** | yes | no | FAIL | -| `xxh3` | 128 | `hash_extra.h` + `:hash_extra_cc` | no | **BSD-2 - ship NOTICE** | yes | no | FAIL | +| Algorithm | Bits | SMHasher3 | Seeded | Streaming | Starlark | NOTICE | Available via | +| ----------- | ---: | --------- | ------ | --------- | -------- | ----------------------- | --------------------------------- | +| `mumbo` | 64 | **PASS** | yes | **yes** | **yes** | none (in-house) | `hash.h` (default 64/32) | +| `jumbo` | 128 | **PASS** | yes | yes (64) | no | none (in-house) | `hash.h` (default 128) | +| `murmur3` | 128 | FAIL | yes | no | no | none (public domain) | `hash.h` | +| `siphash` | 64 | **PASS** | keyed | **yes** | no | none (CC0) | `hash.h` | +| `fnv1a` | 64 | FAIL | yes | no | **yes** | none (public domain) | `hash.h` | +| `dumbo` | 64 | **PASS** | yes | no | **yes** | none (in-house) | `hash.h` | +| `rapidhash` | 64 | **PASS** | yes | no | no | **MIT - ship NOTICE** | `hash_extra.h` + `:hash_extra_cc` | +| `xxh64` | 64 | FAIL | yes | **yes** | no | **BSD-2 - ship NOTICE** | `hash_extra.h` + `:hash_extra_cc` | +| `xxh3` | 64 | FAIL | yes | no | no | **BSD-2 - ship NOTICE** | `hash_extra.h` + `:hash_extra_cc` | +| `xxh3` | 128 | FAIL | yes | no | no | **BSD-2 - ship NOTICE** | `hash_extra.h` + `:hash_extra_cc` | -Notes: the **Starlark** column marks the hashes also implemented at build time -in [`hash.bzl`](hash.bzl) (`hash.mumbo`, `hash.dumbo`, `hash.fnv1a`), kept -byte-for-byte identical to the C++ prime and verified against it (`hash_tool`); -only the one-shot 64-bit form is ported, so the native 128-bit `jumbo` and -streaming stay C++-only. `fnv1a` is the algorithm family many `std::hash` -implementations use (e.g. MSVC) - included as the familiar baseline. `siphash` -is a keyed PRF: the DoS-resistant choice when the seed is a secret. `dumbo` is -the compact single-lane member of the MUM family: the fastest hash here for tiny -keys and SMHasher3-clean (see the design iterations), but single-lane (so it -slows on large keys) - a deliberately minimal companion to `mumbo`, not a -replacement for it. Linking `:hash_extra_cc` requires shipping the -repository-root [NOTICE](../../NOTICE) (see "Third-party components" in the -[repository README](../../README.md)). +Notes: the **Starlark** column marks the hashes that are also implemented in +Starlark for direct buil-graph construction-time[`hash.bzl`](hash.bzl) usage. +Thos are algorithms are (`hash.mumbo`, `hash.dumbo`, `hash.fnv1a`). They are +byte-for-byte identical to the C++ prime and verified against it (`hash_tool`). +Only the one-shot 64-bit form is ported, so the native 128-bit `jumbo` and +streaming stay C++-only. + +Note the following algorithm specifics: + +- `fnv1a` represents the algorithm family many `std::hash` implementations use + (e.g. MSVC) and is thus included as the familiar baseline. +- `siphash` is a keyed PRF. It is the DoS-resistant choice when the seed is a + secret. +- `dumbo` is the compact single-lane member of the mbo MUM family. It is the + fastest hash here for tiny keys and still SMHasher3-clean, but it is also a + single-lane implementation and so it slows on large keys. It is a deliberate + minimal companion to `mumbo` (not a replacement for it). + +Linking `:hash_extra_cc` requires shipping the repository-root [NOTICE](../../NOTICE) +(see "Third-party components" in the [repository README](../../README.md)). ## Build-seed mangle (`hash_mangle.h` / `:hash_mangle_cc`) `mbo::hash::GetHash` and `MangledHasher` equal `GetHash64` XORed with ONE build-selected constant, so values deliberately do not compare across independently configured builds - precomputed tables or persisted values -cannot silently become load-bearing. Everything stays constexpr: the constant +cannot silently become load-bearing. Everything stays `constexpr`: the constant is generated into a header by folding the module's own version (from `MODULE.bazel` via `native.module_version()` - no duplicated version declaration anywhere) with two custom Bazel flags (see the @@ -138,7 +149,7 @@ shape the implementation: entry point participates in constant evaluation, including `GetHash`. True ASLR (absl-style: mixing in the address of a global) or any startup-time random seed cannot appear in a constant expression - adopting one would - split the API into a constexpr unmangled half and a runtime mangled half. + split the API into a `constexpr` unmangled half and a runtime mangled half. The entropy must be a compile-time constant, so it can only be injected at build time. @@ -231,7 +242,7 @@ fallback constant under `-DIS_CLANGD` purely so the editor can parse it. The two frameworks compose rather than compete - pick by contract: `absl::Hash` is per-process randomized and tuned for tiny in-process keys; -`mbo::hash` is canonical, cross-platform, constexpr, and streamable. +`mbo::hash` is canonical, cross-platform, `constexpr`, and streamable. - **Containers**: `DefaultHasher` (any `Hasher` / `MangledHasher`) drops into `absl`/`std` hash containers as the `Hash` parameter for string @@ -267,7 +278,7 @@ The two frameworks compose rather than compete - pick by contract: hash state implementing `combine` / `combine_contiguous` (plus unordered support) can execute every existing `AbslHashValue` overload, so a mumbo-backed state could swap the algorithm underneath all absl-hashable - types. Worth it only when structured types need canonical or constexpr + types. Worth it only when structured types need canonical or `constexpr` hashing; for byte keys the container functor above already does the job. ## Performance @@ -718,14 +729,14 @@ numbers are directly comparable. | Algorithm | Bits | Role in mbo/hash | SMHasher3 result | Failures | | ----------- | ---: | ------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `dumbo` | 64 | `hash.h` (compact MUM) | PASS | none | +| `dumbo` | 64 | `hash.h` (compact MUM) | **PASS** | none | | `fnv1a` | 64 | `hash.h` | 7/186 | Avalanche [3, 4, 5, 6, 7, 8, 9, 10, 12, 16, 20, 64, 128], BIC [3, 8, 11, 15], Zeroes [], Cyclic [4 cycles of 3 bytes, 4 cycles of 4 bytes, 4 cycles of 5 bytes, 4 cycles of 8 bytes, 8 cycles of 3 bytes, 8 cycles of 4 bytes, 8 cycles of 5 bytes, 8 cycles of 8 bytes, 12 cycles of 3 bytes, 12 cycles of 4 bytes, 12 cycles of 5 bytes, 12 cycles of 8 bytes, 16 cycles of 3 bytes, 16 cycles of 4 bytes, 16 cycles of 5 bytes, 16 cycles of 8 bytes], Sparse [6/2, 4/3, 4/4, 4/5, 3/6, 3/7, 3/8, 3/9, 3/10, 3/12, 3/14, 10/2, 20/3, 9/4, 5/9, 4/14, 4/16, 3/32, 3/48, 3/64, 3/96, 2/128, 2/256, 2/512, 2/1024, 2/1280] | -| `mumbo` | 64 | default (64/32/streaming) | PASS | none | -| `rapidhash` | 64 | extra (`hash_extra_cc`) | PASS | none | -| `siphash` | 64 | `hash.h` (keyed PRF) | PASS | none | +| `mumbo` | 64 | default (64/32/streaming) | **PASS** | none | +| `rapidhash` | 64 | extra (`hash_extra_cc`) | **PASS** | none | +| `siphash` | 64 | `hash.h` (keyed PRF) | **PASS** | none | | `xxh3` | 64 | extra (`hash_extra_cc`) | 166/188 | BIC [3, 8, 11], Sparse [20/3], PerlinNoise [2], Bitflip [8], SeedZeroes [1280, 8448], SeedSparse [2, 3], SeedBlockLen [8, 13, 14, 15, 16], SeedBlockOffset [0, 1, 2, 3, 4], SeedBIC [3, 8] | | `xxh64` | 64 | extra (`hash_extra_cc`) | 181/188 | SeedBlockLen [15, 19, 21, 26, 29, 30], SeedBIC [8] | -| `jumbo` | 128 | default (128) | PASS | none | +| `jumbo` | 128 | default (128) | **PASS** | none | | `murmur3` | 128 | `hash.h` | 123/188 | BIC [3], Zeroes [] | | `xxh3` | 128 | extra (`hash_extra_cc`) | 162/188 | BIC [3, 8, 15], Sparse [20/3], PerlinNoise [2], Bitflip [3, 4, 8], SeedZeroes [1280, 8448], SeedSparse [2, 3], SeedBlockLen [8, 12, 13, 14, 15, 16], SeedBlockOffset [0, 1, 2, 3, 4, 5], SeedBIC [3, 8] | @@ -870,7 +881,7 @@ reads as the compact MUM hash rather than a second tuned one: # Re-render this README from the chosen bundles, then refresh the SMHasher3 # Results table from the same bundle's measured data. - mbo/hash/measurements/hash_benchmark_report.py publish --bundles data/.tgz - mbo/hash/measurements/hash_benchmark_report.py quality --smhasher data/.tgz + mbo/hash/measurements/hash_benchmark_report.py publish --bundles data/.tgz ... + mbo/hash/measurements/hash_benchmark_report.py quality data/.tgz git add mbo/hash/README.md mbo/hash/measurements/charts ```