From 4a1e0bb078b19dc46a86392018d49d4cd062aab3 Mon Sep 17 00:00:00 2001 From: Dmitrii Krosh Date: Thu, 2 Jul 2026 15:19:31 +0300 Subject: [PATCH] testing hash --- for_me.md | 4 + hash_testing/build_collizions.sh | 27 ++ hash_testing/build_collizions_ascii.sh | 27 ++ hash_testing/build_speed.sh | 27 ++ hash_testing/collizions.cpp | 199 ++++++++++++++ hash_testing/collizions/city32.out | 49 ++++ hash_testing/collizions/city64.out | 49 ++++ hash_testing/collizions/joaat.out | 49 ++++ hash_testing/collizions/xxh32.out | 49 ++++ hash_testing/collizions/xxh3_64.out | 49 ++++ hash_testing/collizions/xxh64.out | 49 ++++ hash_testing/collizions_ascii.cpp | 206 ++++++++++++++ hash_testing/collizions_ascii/city32.out | 49 ++++ hash_testing/collizions_ascii/city64.out | 49 ++++ hash_testing/collizions_ascii/joaat.out | 49 ++++ hash_testing/collizions_ascii/xxh32.out | 49 ++++ hash_testing/collizions_ascii/xxh3_64.out | 49 ++++ hash_testing/collizions_ascii/xxh64.out | 49 ++++ hash_testing/graphs.py | 245 +++++++++++++++++ hash_testing/graphs/collizions.svg | 304 +++++++++++++++++++++ hash_testing/graphs/collizions_ascii.svg | 312 ++++++++++++++++++++++ hash_testing/graphs/speed.svg | 72 +++++ hash_testing/speed.cpp | 192 +++++++++++++ hash_testing/speed/city32.out | 14 + hash_testing/speed/city64.out | 14 + hash_testing/speed/joaat.out | 14 + hash_testing/speed/xxh32.out | 14 + hash_testing/speed/xxh3_64.out | 14 + hash_testing/speed/xxh64.out | 14 + hash_testing/src/cityhash | 1 + hash_testing/src/joaat/hash.c | 46 ++++ hash_testing/src/joaat/hash.h | 21 ++ hash_testing/src/xxHash | 1 + 33 files changed, 2356 insertions(+) create mode 100755 hash_testing/build_collizions.sh create mode 100755 hash_testing/build_collizions_ascii.sh create mode 100755 hash_testing/build_speed.sh create mode 100644 hash_testing/collizions.cpp create mode 100644 hash_testing/collizions/city32.out create mode 100644 hash_testing/collizions/city64.out create mode 100644 hash_testing/collizions/joaat.out create mode 100644 hash_testing/collizions/xxh32.out create mode 100644 hash_testing/collizions/xxh3_64.out create mode 100644 hash_testing/collizions/xxh64.out create mode 100644 hash_testing/collizions_ascii.cpp create mode 100644 hash_testing/collizions_ascii/city32.out create mode 100644 hash_testing/collizions_ascii/city64.out create mode 100644 hash_testing/collizions_ascii/joaat.out create mode 100644 hash_testing/collizions_ascii/xxh32.out create mode 100644 hash_testing/collizions_ascii/xxh3_64.out create mode 100644 hash_testing/collizions_ascii/xxh64.out create mode 100644 hash_testing/graphs.py create mode 100644 hash_testing/graphs/collizions.svg create mode 100644 hash_testing/graphs/collizions_ascii.svg create mode 100644 hash_testing/graphs/speed.svg create mode 100644 hash_testing/speed.cpp create mode 100644 hash_testing/speed/city32.out create mode 100644 hash_testing/speed/city64.out create mode 100644 hash_testing/speed/joaat.out create mode 100644 hash_testing/speed/xxh32.out create mode 100644 hash_testing/speed/xxh3_64.out create mode 100644 hash_testing/speed/xxh64.out create mode 160000 hash_testing/src/cityhash create mode 100644 hash_testing/src/joaat/hash.c create mode 100644 hash_testing/src/joaat/hash.h create mode 160000 hash_testing/src/xxHash diff --git a/for_me.md b/for_me.md index 397eafe..44a3fa8 100644 --- a/for_me.md +++ b/for_me.md @@ -1,5 +1,9 @@ # Notes +## to read + +https://www.altlinux.org/Features/Specific + ## Hash в данный момент используется Jenkins OAAT. Считается чуть устаревшим(check), главным аналогом является: diff --git a/hash_testing/build_collizions.sh b/hash_testing/build_collizions.sh new file mode 100755 index 0000000..b7e5473 --- /dev/null +++ b/hash_testing/build_collizions.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")" + +mkdir -p build + +cat > build/config.h <<'EOF' +#define HAVE_STDINT_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STDLIB_H 1 +EOF + +cc -O3 -std=c99 -Wall -Wextra -Werror -I. \ + -c src/joaat/hash.c -o build/joaat.o + +cc -O3 -std=c99 -Wall -Wextra -Werror -I. \ + -c src/xxHash/xxhash.c -o build/xxhash.o + +g++ -O3 -std=c++17 -Wall -Wextra -Werror \ + -I. -Ibuild -Isrc/cityhash/src \ + collizions.cpp src/cityhash/src/city.cc build/joaat.o build/xxhash.o \ + -o build/collizions_test + +# Args are passed through to collizions_test: +# ./build_collizions.sh [runs=5] [samples=50000] +./build/collizions_test "$@" diff --git a/hash_testing/build_collizions_ascii.sh b/hash_testing/build_collizions_ascii.sh new file mode 100755 index 0000000..bdf5cbc --- /dev/null +++ b/hash_testing/build_collizions_ascii.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")" + +mkdir -p build + +cat > build/config.h <<'EOF' +#define HAVE_STDINT_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STDLIB_H 1 +EOF + +cc -O3 -std=c99 -Wall -Wextra -Werror -I. \ + -c src/joaat/hash.c -o build/joaat.o + +cc -O3 -std=c99 -Wall -Wextra -Werror -I. \ + -c src/xxHash/xxhash.c -o build/xxhash.o + +g++ -O3 -std=c++17 -Wall -Wextra -Werror \ + -I. -Ibuild -Isrc/cityhash/src \ + collizions_ascii.cpp src/cityhash/src/city.cc build/joaat.o build/xxhash.o \ + -o build/collizions_ascii_test + +# Args are passed through to collizions_ascii_test: +# ./build_collizions_ascii.sh [runs=5] [samples=50000] +./build/collizions_ascii_test "$@" diff --git a/hash_testing/build_speed.sh b/hash_testing/build_speed.sh new file mode 100755 index 0000000..9f7cad9 --- /dev/null +++ b/hash_testing/build_speed.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")" + +mkdir -p build + +cat > build/config.h <<'EOF' +#define HAVE_STDINT_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STDLIB_H 1 +EOF + +cc -O3 -std=c99 -Wall -Wextra -Werror -I. \ + -c src/joaat/hash.c -o build/joaat.o + +cc -O3 -std=c99 -Wall -Wextra -Werror -I. \ + -c src/xxHash/xxhash.c -o build/xxhash.o + +g++ -O3 -std=c++17 -Wall -Wextra -Werror \ + -I. -Ibuild -Isrc/cityhash/src \ + speed.cpp src/cityhash/src/city.cc build/joaat.o build/xxhash.o \ + -o build/speed_test + +# Args are passed through to speed_test: +# ./build_speed.sh [runs=7] [target_mib_per_run=32] [max_iters=200000] +./build/speed_test "$@" diff --git a/hash_testing/collizions.cpp b/hash_testing/collizions.cpp new file mode 100644 index 0000000..5b5573c --- /dev/null +++ b/hash_testing/collizions.cpp @@ -0,0 +1,199 @@ +/* +Compare hash collision rates on random byte strings. + +Output: collizions/{hash_name}.out, CSV, one row per input length and bit width. + +Build example: + cc -O3 -I. -c src/joaat/hash.c -o joaat.o + cc -O3 -I. -c src/xxHash/xxhash.c -o xxhash.o + g++ -O3 -std=c++17 -I. -Isrc/cityhash/src collizions.cpp \ + src/cityhash/src/city.cc joaat.o xxhash.o -o collizions_test + +Run: + ./collizions_test [runs=5] [samples=50000] +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/cityhash/src/city.h" +#include "src/joaat/hash.h" +#include "src/xxHash/xxhash.h" + +namespace fs = std::filesystem; + +using HashFn = uint64_t (*)(const void *, size_t); + +struct HashCase { + std::string_view name; + HashFn fn; +}; + +struct CollisionStats { + size_t collisions; + size_t unique; +}; + +static uint64_t hash_xxh32(const void *data, size_t len) +{ + return XXH32(data, len, 0); +} + +static uint64_t hash_xxh64(const void *data, size_t len) +{ + return XXH64(data, len, 0); +} + +static uint64_t hash_xxh3_64(const void *data, size_t len) +{ + return XXH3_64bits(data, len); +} + +static uint64_t hash_city32(const void *data, size_t len) +{ + return CityHash32(static_cast(data), len); +} + +static uint64_t hash_city64(const void *data, size_t len) +{ + return CityHash64(static_cast(data), len); +} + +static uint64_t hash_joaat(const void *data, size_t len) +{ + return joaat_hash_bytes(data, len); +} + +static uint64_t bit_mask(unsigned bits) +{ + return bits >= 64 ? ~0ULL : ((1ULL << bits) - 1ULL); +} + +static double median(std::vector values) +{ + const size_t mid = values.size() / 2; + std::nth_element(values.begin(), values.begin() + mid, values.end()); + if (values.size() % 2 != 0) { + return values[mid]; + } + + const double hi = values[mid]; + std::nth_element(values.begin(), values.begin() + mid - 1, values.end()); + return (values[mid - 1] + hi) / 2.0; +} + +static std::vector random_bytes(size_t len, uint64_t seed) +{ + std::vector data(len); + std::mt19937_64 rng(seed); + for (unsigned char &byte : data) { + byte = static_cast(rng() & 0xffu); + } + return data; +} + +static std::vector random_hashes(HashFn fn, size_t len, size_t samples, uint64_t seed) +{ + std::vector hashes; + hashes.reserve(samples); + + std::mt19937_64 seed_rng(seed); + for (size_t i = 0; i < samples; ++i) { + const std::vector data = random_bytes(len, seed_rng()); + hashes.push_back(fn(data.data(), data.size())); + } + + return hashes; +} + +static CollisionStats count_collisions(const std::vector &hashes, unsigned bits) +{ + std::unordered_set seen; + seen.reserve(hashes.size() * 2); + + const uint64_t mask = bit_mask(bits); + for (uint64_t hash : hashes) { + seen.insert(hash & mask); + } + + return {hashes.size() - seen.size(), seen.size()}; +} + +int main(int argc, char **argv) +{ + const int runs = argc > 1 ? std::max(1, std::atoi(argv[1])) : 5; + const size_t samples = argc > 2 ? std::max(1, std::atoi(argv[2])) : 50000; + + const std::vector lengths = {1, 4, 8, 16, 32, 64, 128, 256}; + const std::vector bit_widths = {10, 12, 16, 20, 24, 32}; + const std::vector hashes = { + {"xxh32", hash_xxh32}, + {"xxh64", hash_xxh64}, + {"xxh3_64", hash_xxh3_64}, + {"city32", hash_city32}, + {"city64", hash_city64}, + {"joaat", hash_joaat}, + }; + + const fs::path out_dir = fs::path(__FILE__).stem(); + fs::create_directories(out_dir); + + for (const HashCase &hash : hashes) { + const fs::path out_path = out_dir / (std::string(hash.name) + ".out"); + std::ofstream out(out_path); + if (!out) { + std::cerr << "failed to open " << out_path << '\n'; + return 1; + } + + out << "hash,length,bits,samples,runs,median_collisions,median_collision_rate,median_unique\n"; + out << std::fixed << std::setprecision(8); + + for (size_t len : lengths) { + std::vector> run_hashes; + run_hashes.reserve(runs); + + for (int run = 0; run < runs; ++run) { + const uint64_t seed = 0x415253565f636f6cULL ^ (len << 8) ^ run; + run_hashes.push_back(random_hashes(hash.fn, len, samples, seed)); + } + + for (unsigned bits : bit_widths) { + std::vector collision_values; + std::vector unique_values; + collision_values.reserve(runs); + unique_values.reserve(runs); + + for (const auto &hashes_for_run : run_hashes) { + const CollisionStats stats = count_collisions(hashes_for_run, bits); + collision_values.push_back(static_cast(stats.collisions)); + unique_values.push_back(static_cast(stats.unique)); + } + + const double median_collisions = median(collision_values); + const double median_unique = median(unique_values); + out << hash.name << ',' + << len << ',' + << bits << ',' + << samples << ',' + << runs << ',' + << median_collisions << ',' + << (median_collisions / static_cast(samples)) << ',' + << median_unique << '\n'; + } + } + } + + std::cerr << "wrote " << out_dir << "/*.out\n"; + return 0; +} diff --git a/hash_testing/collizions/city32.out b/hash_testing/collizions/city32.out new file mode 100644 index 0000000..0d7b062 --- /dev/null +++ b/hash_testing/collizions/city32.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,median_collisions,median_collision_rate,median_unique +city32,1,10,1000,3,782.00000000,0.78200000,218.00000000 +city32,1,12,1000,3,758.00000000,0.75800000,242.00000000 +city32,1,16,1000,3,751.00000000,0.75100000,249.00000000 +city32,1,20,1000,3,751.00000000,0.75100000,249.00000000 +city32,1,24,1000,3,751.00000000,0.75100000,249.00000000 +city32,1,32,1000,3,751.00000000,0.75100000,249.00000000 +city32,4,10,1000,3,358.00000000,0.35800000,642.00000000 +city32,4,12,1000,3,110.00000000,0.11000000,890.00000000 +city32,4,16,1000,3,6.00000000,0.00600000,994.00000000 +city32,4,20,1000,3,0.00000000,0.00000000,1000.00000000 +city32,4,24,1000,3,0.00000000,0.00000000,1000.00000000 +city32,4,32,1000,3,0.00000000,0.00000000,1000.00000000 +city32,8,10,1000,3,363.00000000,0.36300000,637.00000000 +city32,8,12,1000,3,114.00000000,0.11400000,886.00000000 +city32,8,16,1000,3,8.00000000,0.00800000,992.00000000 +city32,8,20,1000,3,0.00000000,0.00000000,1000.00000000 +city32,8,24,1000,3,0.00000000,0.00000000,1000.00000000 +city32,8,32,1000,3,0.00000000,0.00000000,1000.00000000 +city32,16,10,1000,3,351.00000000,0.35100000,649.00000000 +city32,16,12,1000,3,108.00000000,0.10800000,892.00000000 +city32,16,16,1000,3,6.00000000,0.00600000,994.00000000 +city32,16,20,1000,3,0.00000000,0.00000000,1000.00000000 +city32,16,24,1000,3,0.00000000,0.00000000,1000.00000000 +city32,16,32,1000,3,0.00000000,0.00000000,1000.00000000 +city32,32,10,1000,3,360.00000000,0.36000000,640.00000000 +city32,32,12,1000,3,112.00000000,0.11200000,888.00000000 +city32,32,16,1000,3,9.00000000,0.00900000,991.00000000 +city32,32,20,1000,3,0.00000000,0.00000000,1000.00000000 +city32,32,24,1000,3,0.00000000,0.00000000,1000.00000000 +city32,32,32,1000,3,0.00000000,0.00000000,1000.00000000 +city32,64,10,1000,3,354.00000000,0.35400000,646.00000000 +city32,64,12,1000,3,112.00000000,0.11200000,888.00000000 +city32,64,16,1000,3,4.00000000,0.00400000,996.00000000 +city32,64,20,1000,3,1.00000000,0.00100000,999.00000000 +city32,64,24,1000,3,0.00000000,0.00000000,1000.00000000 +city32,64,32,1000,3,0.00000000,0.00000000,1000.00000000 +city32,128,10,1000,3,356.00000000,0.35600000,644.00000000 +city32,128,12,1000,3,108.00000000,0.10800000,892.00000000 +city32,128,16,1000,3,7.00000000,0.00700000,993.00000000 +city32,128,20,1000,3,0.00000000,0.00000000,1000.00000000 +city32,128,24,1000,3,0.00000000,0.00000000,1000.00000000 +city32,128,32,1000,3,0.00000000,0.00000000,1000.00000000 +city32,256,10,1000,3,358.00000000,0.35800000,642.00000000 +city32,256,12,1000,3,103.00000000,0.10300000,897.00000000 +city32,256,16,1000,3,6.00000000,0.00600000,994.00000000 +city32,256,20,1000,3,0.00000000,0.00000000,1000.00000000 +city32,256,24,1000,3,0.00000000,0.00000000,1000.00000000 +city32,256,32,1000,3,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions/city64.out b/hash_testing/collizions/city64.out new file mode 100644 index 0000000..c728ef8 --- /dev/null +++ b/hash_testing/collizions/city64.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,median_collisions,median_collision_rate,median_unique +city64,1,10,1000,3,784.00000000,0.78400000,216.00000000 +city64,1,12,1000,3,758.00000000,0.75800000,242.00000000 +city64,1,16,1000,3,751.00000000,0.75100000,249.00000000 +city64,1,20,1000,3,751.00000000,0.75100000,249.00000000 +city64,1,24,1000,3,751.00000000,0.75100000,249.00000000 +city64,1,32,1000,3,751.00000000,0.75100000,249.00000000 +city64,4,10,1000,3,369.00000000,0.36900000,631.00000000 +city64,4,12,1000,3,111.00000000,0.11100000,889.00000000 +city64,4,16,1000,3,10.00000000,0.01000000,990.00000000 +city64,4,20,1000,3,1.00000000,0.00100000,999.00000000 +city64,4,24,1000,3,0.00000000,0.00000000,1000.00000000 +city64,4,32,1000,3,0.00000000,0.00000000,1000.00000000 +city64,8,10,1000,3,359.00000000,0.35900000,641.00000000 +city64,8,12,1000,3,119.00000000,0.11900000,881.00000000 +city64,8,16,1000,3,8.00000000,0.00800000,992.00000000 +city64,8,20,1000,3,0.00000000,0.00000000,1000.00000000 +city64,8,24,1000,3,0.00000000,0.00000000,1000.00000000 +city64,8,32,1000,3,0.00000000,0.00000000,1000.00000000 +city64,16,10,1000,3,362.00000000,0.36200000,638.00000000 +city64,16,12,1000,3,100.00000000,0.10000000,900.00000000 +city64,16,16,1000,3,6.00000000,0.00600000,994.00000000 +city64,16,20,1000,3,1.00000000,0.00100000,999.00000000 +city64,16,24,1000,3,0.00000000,0.00000000,1000.00000000 +city64,16,32,1000,3,0.00000000,0.00000000,1000.00000000 +city64,32,10,1000,3,364.00000000,0.36400000,636.00000000 +city64,32,12,1000,3,113.00000000,0.11300000,887.00000000 +city64,32,16,1000,3,8.00000000,0.00800000,992.00000000 +city64,32,20,1000,3,0.00000000,0.00000000,1000.00000000 +city64,32,24,1000,3,0.00000000,0.00000000,1000.00000000 +city64,32,32,1000,3,0.00000000,0.00000000,1000.00000000 +city64,64,10,1000,3,352.00000000,0.35200000,648.00000000 +city64,64,12,1000,3,111.00000000,0.11100000,889.00000000 +city64,64,16,1000,3,12.00000000,0.01200000,988.00000000 +city64,64,20,1000,3,0.00000000,0.00000000,1000.00000000 +city64,64,24,1000,3,0.00000000,0.00000000,1000.00000000 +city64,64,32,1000,3,0.00000000,0.00000000,1000.00000000 +city64,128,10,1000,3,361.00000000,0.36100000,639.00000000 +city64,128,12,1000,3,120.00000000,0.12000000,880.00000000 +city64,128,16,1000,3,8.00000000,0.00800000,992.00000000 +city64,128,20,1000,3,0.00000000,0.00000000,1000.00000000 +city64,128,24,1000,3,0.00000000,0.00000000,1000.00000000 +city64,128,32,1000,3,0.00000000,0.00000000,1000.00000000 +city64,256,10,1000,3,350.00000000,0.35000000,650.00000000 +city64,256,12,1000,3,100.00000000,0.10000000,900.00000000 +city64,256,16,1000,3,5.00000000,0.00500000,995.00000000 +city64,256,20,1000,3,0.00000000,0.00000000,1000.00000000 +city64,256,24,1000,3,0.00000000,0.00000000,1000.00000000 +city64,256,32,1000,3,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions/joaat.out b/hash_testing/collizions/joaat.out new file mode 100644 index 0000000..1061e6e --- /dev/null +++ b/hash_testing/collizions/joaat.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,median_collisions,median_collision_rate,median_unique +joaat,1,10,1000,3,773.00000000,0.77300000,227.00000000 +joaat,1,12,1000,3,755.00000000,0.75500000,245.00000000 +joaat,1,16,1000,3,751.00000000,0.75100000,249.00000000 +joaat,1,20,1000,3,751.00000000,0.75100000,249.00000000 +joaat,1,24,1000,3,751.00000000,0.75100000,249.00000000 +joaat,1,32,1000,3,751.00000000,0.75100000,249.00000000 +joaat,4,10,1000,3,361.00000000,0.36100000,639.00000000 +joaat,4,12,1000,3,109.00000000,0.10900000,891.00000000 +joaat,4,16,1000,3,8.00000000,0.00800000,992.00000000 +joaat,4,20,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,4,24,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,4,32,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,8,10,1000,3,364.00000000,0.36400000,636.00000000 +joaat,8,12,1000,3,124.00000000,0.12400000,876.00000000 +joaat,8,16,1000,3,8.00000000,0.00800000,992.00000000 +joaat,8,20,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,8,24,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,8,32,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,16,10,1000,3,364.00000000,0.36400000,636.00000000 +joaat,16,12,1000,3,117.00000000,0.11700000,883.00000000 +joaat,16,16,1000,3,9.00000000,0.00900000,991.00000000 +joaat,16,20,1000,3,1.00000000,0.00100000,999.00000000 +joaat,16,24,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,16,32,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,32,10,1000,3,365.00000000,0.36500000,635.00000000 +joaat,32,12,1000,3,110.00000000,0.11000000,890.00000000 +joaat,32,16,1000,3,7.00000000,0.00700000,993.00000000 +joaat,32,20,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,32,24,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,32,32,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,64,10,1000,3,360.00000000,0.36000000,640.00000000 +joaat,64,12,1000,3,107.00000000,0.10700000,893.00000000 +joaat,64,16,1000,3,7.00000000,0.00700000,993.00000000 +joaat,64,20,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,64,24,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,64,32,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,128,10,1000,3,363.00000000,0.36300000,637.00000000 +joaat,128,12,1000,3,114.00000000,0.11400000,886.00000000 +joaat,128,16,1000,3,4.00000000,0.00400000,996.00000000 +joaat,128,20,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,128,24,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,128,32,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,256,10,1000,3,356.00000000,0.35600000,644.00000000 +joaat,256,12,1000,3,120.00000000,0.12000000,880.00000000 +joaat,256,16,1000,3,7.00000000,0.00700000,993.00000000 +joaat,256,20,1000,3,1.00000000,0.00100000,999.00000000 +joaat,256,24,1000,3,0.00000000,0.00000000,1000.00000000 +joaat,256,32,1000,3,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions/xxh32.out b/hash_testing/collizions/xxh32.out new file mode 100644 index 0000000..5d9f2bc --- /dev/null +++ b/hash_testing/collizions/xxh32.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,median_collisions,median_collision_rate,median_unique +xxh32,1,10,1000,3,781.00000000,0.78100000,219.00000000 +xxh32,1,12,1000,3,760.00000000,0.76000000,240.00000000 +xxh32,1,16,1000,3,753.00000000,0.75300000,247.00000000 +xxh32,1,20,1000,3,751.00000000,0.75100000,249.00000000 +xxh32,1,24,1000,3,751.00000000,0.75100000,249.00000000 +xxh32,1,32,1000,3,751.00000000,0.75100000,249.00000000 +xxh32,4,10,1000,3,372.00000000,0.37200000,628.00000000 +xxh32,4,12,1000,3,121.00000000,0.12100000,879.00000000 +xxh32,4,16,1000,3,8.00000000,0.00800000,992.00000000 +xxh32,4,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,4,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,4,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,8,10,1000,3,370.00000000,0.37000000,630.00000000 +xxh32,8,12,1000,3,106.00000000,0.10600000,894.00000000 +xxh32,8,16,1000,3,6.00000000,0.00600000,994.00000000 +xxh32,8,20,1000,3,1.00000000,0.00100000,999.00000000 +xxh32,8,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,8,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,16,10,1000,3,363.00000000,0.36300000,637.00000000 +xxh32,16,12,1000,3,109.00000000,0.10900000,891.00000000 +xxh32,16,16,1000,3,6.00000000,0.00600000,994.00000000 +xxh32,16,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,16,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,16,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,32,10,1000,3,366.00000000,0.36600000,634.00000000 +xxh32,32,12,1000,3,116.00000000,0.11600000,884.00000000 +xxh32,32,16,1000,3,7.00000000,0.00700000,993.00000000 +xxh32,32,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,32,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,32,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,64,10,1000,3,366.00000000,0.36600000,634.00000000 +xxh32,64,12,1000,3,119.00000000,0.11900000,881.00000000 +xxh32,64,16,1000,3,10.00000000,0.01000000,990.00000000 +xxh32,64,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,64,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,64,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,128,10,1000,3,359.00000000,0.35900000,641.00000000 +xxh32,128,12,1000,3,112.00000000,0.11200000,888.00000000 +xxh32,128,16,1000,3,6.00000000,0.00600000,994.00000000 +xxh32,128,20,1000,3,1.00000000,0.00100000,999.00000000 +xxh32,128,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,128,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,256,10,1000,3,366.00000000,0.36600000,634.00000000 +xxh32,256,12,1000,3,112.00000000,0.11200000,888.00000000 +xxh32,256,16,1000,3,4.00000000,0.00400000,996.00000000 +xxh32,256,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,256,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh32,256,32,1000,3,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions/xxh3_64.out b/hash_testing/collizions/xxh3_64.out new file mode 100644 index 0000000..e922782 --- /dev/null +++ b/hash_testing/collizions/xxh3_64.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,median_collisions,median_collision_rate,median_unique +xxh3_64,1,10,1000,3,776.00000000,0.77600000,224.00000000 +xxh3_64,1,12,1000,3,752.00000000,0.75200000,248.00000000 +xxh3_64,1,16,1000,3,751.00000000,0.75100000,249.00000000 +xxh3_64,1,20,1000,3,751.00000000,0.75100000,249.00000000 +xxh3_64,1,24,1000,3,751.00000000,0.75100000,249.00000000 +xxh3_64,1,32,1000,3,751.00000000,0.75100000,249.00000000 +xxh3_64,4,10,1000,3,366.00000000,0.36600000,634.00000000 +xxh3_64,4,12,1000,3,121.00000000,0.12100000,879.00000000 +xxh3_64,4,16,1000,3,7.00000000,0.00700000,993.00000000 +xxh3_64,4,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,4,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,4,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,8,10,1000,3,355.00000000,0.35500000,645.00000000 +xxh3_64,8,12,1000,3,110.00000000,0.11000000,890.00000000 +xxh3_64,8,16,1000,3,7.00000000,0.00700000,993.00000000 +xxh3_64,8,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,8,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,8,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,16,10,1000,3,353.00000000,0.35300000,647.00000000 +xxh3_64,16,12,1000,3,107.00000000,0.10700000,893.00000000 +xxh3_64,16,16,1000,3,8.00000000,0.00800000,992.00000000 +xxh3_64,16,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,16,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,16,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,32,10,1000,3,364.00000000,0.36400000,636.00000000 +xxh3_64,32,12,1000,3,108.00000000,0.10800000,892.00000000 +xxh3_64,32,16,1000,3,8.00000000,0.00800000,992.00000000 +xxh3_64,32,20,1000,3,1.00000000,0.00100000,999.00000000 +xxh3_64,32,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,32,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,64,10,1000,3,370.00000000,0.37000000,630.00000000 +xxh3_64,64,12,1000,3,114.00000000,0.11400000,886.00000000 +xxh3_64,64,16,1000,3,6.00000000,0.00600000,994.00000000 +xxh3_64,64,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,64,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,64,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,128,10,1000,3,364.00000000,0.36400000,636.00000000 +xxh3_64,128,12,1000,3,112.00000000,0.11200000,888.00000000 +xxh3_64,128,16,1000,3,7.00000000,0.00700000,993.00000000 +xxh3_64,128,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,128,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,128,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,256,10,1000,3,367.00000000,0.36700000,633.00000000 +xxh3_64,256,12,1000,3,118.00000000,0.11800000,882.00000000 +xxh3_64,256,16,1000,3,9.00000000,0.00900000,991.00000000 +xxh3_64,256,20,1000,3,1.00000000,0.00100000,999.00000000 +xxh3_64,256,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh3_64,256,32,1000,3,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions/xxh64.out b/hash_testing/collizions/xxh64.out new file mode 100644 index 0000000..35e8d30 --- /dev/null +++ b/hash_testing/collizions/xxh64.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,median_collisions,median_collision_rate,median_unique +xxh64,1,10,1000,3,782.00000000,0.78200000,218.00000000 +xxh64,1,12,1000,3,761.00000000,0.76100000,239.00000000 +xxh64,1,16,1000,3,752.00000000,0.75200000,248.00000000 +xxh64,1,20,1000,3,751.00000000,0.75100000,249.00000000 +xxh64,1,24,1000,3,751.00000000,0.75100000,249.00000000 +xxh64,1,32,1000,3,751.00000000,0.75100000,249.00000000 +xxh64,4,10,1000,3,361.00000000,0.36100000,639.00000000 +xxh64,4,12,1000,3,112.00000000,0.11200000,888.00000000 +xxh64,4,16,1000,3,9.00000000,0.00900000,991.00000000 +xxh64,4,20,1000,3,1.00000000,0.00100000,999.00000000 +xxh64,4,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,4,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,8,10,1000,3,359.00000000,0.35900000,641.00000000 +xxh64,8,12,1000,3,109.00000000,0.10900000,891.00000000 +xxh64,8,16,1000,3,10.00000000,0.01000000,990.00000000 +xxh64,8,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,8,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,8,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,16,10,1000,3,365.00000000,0.36500000,635.00000000 +xxh64,16,12,1000,3,113.00000000,0.11300000,887.00000000 +xxh64,16,16,1000,3,7.00000000,0.00700000,993.00000000 +xxh64,16,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,16,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,16,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,32,10,1000,3,362.00000000,0.36200000,638.00000000 +xxh64,32,12,1000,3,118.00000000,0.11800000,882.00000000 +xxh64,32,16,1000,3,10.00000000,0.01000000,990.00000000 +xxh64,32,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,32,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,32,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,64,10,1000,3,349.00000000,0.34900000,651.00000000 +xxh64,64,12,1000,3,111.00000000,0.11100000,889.00000000 +xxh64,64,16,1000,3,8.00000000,0.00800000,992.00000000 +xxh64,64,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,64,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,64,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,128,10,1000,3,364.00000000,0.36400000,636.00000000 +xxh64,128,12,1000,3,119.00000000,0.11900000,881.00000000 +xxh64,128,16,1000,3,9.00000000,0.00900000,991.00000000 +xxh64,128,20,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,128,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,128,32,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,256,10,1000,3,360.00000000,0.36000000,640.00000000 +xxh64,256,12,1000,3,105.00000000,0.10500000,895.00000000 +xxh64,256,16,1000,3,7.00000000,0.00700000,993.00000000 +xxh64,256,20,1000,3,1.00000000,0.00100000,999.00000000 +xxh64,256,24,1000,3,0.00000000,0.00000000,1000.00000000 +xxh64,256,32,1000,3,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions_ascii.cpp b/hash_testing/collizions_ascii.cpp new file mode 100644 index 0000000..bc755d5 --- /dev/null +++ b/hash_testing/collizions_ascii.cpp @@ -0,0 +1,206 @@ +/* +Compare hash collision rates on random ASCII strings using only [a-zA-Z]. + +Output: collizions_ascii/{hash_name}.out, CSV, one row per input length and bit width. + +Build example: + cc -O3 -I. -c src/joaat/hash.c -o joaat.o + cc -O3 -I. -c src/xxHash/xxhash.c -o xxhash.o + g++ -O3 -std=c++17 -I. -Isrc/cityhash/src collizions_ascii.cpp \ + src/cityhash/src/city.cc joaat.o xxhash.o -o collizions_ascii_test + +Run: + ./collizions_ascii_test [runs=5] [samples=50000] +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/cityhash/src/city.h" +#include "src/joaat/hash.h" +#include "src/xxHash/xxhash.h" + +namespace fs = std::filesystem; + +using HashFn = uint64_t (*)(const void *, size_t); + +struct HashCase { + std::string_view name; + HashFn fn; +}; + +struct CollisionStats { + size_t collisions; + size_t unique; +}; + +static uint64_t hash_xxh32(const void *data, size_t len) +{ + return XXH32(data, len, 0); +} + +static uint64_t hash_xxh64(const void *data, size_t len) +{ + return XXH64(data, len, 0); +} + +static uint64_t hash_xxh3_64(const void *data, size_t len) +{ + return XXH3_64bits(data, len); +} + +static uint64_t hash_city32(const void *data, size_t len) +{ + return CityHash32(static_cast(data), len); +} + +static uint64_t hash_city64(const void *data, size_t len) +{ + return CityHash64(static_cast(data), len); +} + +static uint64_t hash_joaat(const void *data, size_t len) +{ + return joaat_hash_bytes(data, len); +} + +static uint64_t bit_mask(unsigned bits) +{ + return bits >= 64 ? ~0ULL : ((1ULL << bits) - 1ULL); +} + +static double median(std::vector values) +{ + const size_t mid = values.size() / 2; + std::nth_element(values.begin(), values.begin() + mid, values.end()); + if (values.size() % 2 != 0) { + return values[mid]; + } + + const double hi = values[mid]; + std::nth_element(values.begin(), values.begin() + mid - 1, values.end()); + return (values[mid - 1] + hi) / 2.0; +} + +static std::string random_ascii_string(size_t len, uint64_t seed) +{ + static constexpr char alphabet[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + static constexpr size_t alphabet_size = sizeof(alphabet) - 1; + + std::string data; + data.resize(len); + + std::mt19937_64 rng(seed); + for (char &ch : data) { + ch = alphabet[rng() % alphabet_size]; + } + + return data; +} + +static std::vector random_hashes(HashFn fn, size_t len, size_t samples, uint64_t seed) +{ + std::vector hashes; + hashes.reserve(samples); + + std::mt19937_64 seed_rng(seed); + for (size_t i = 0; i < samples; ++i) { + const std::string data = random_ascii_string(len, seed_rng()); + hashes.push_back(fn(data.data(), data.size())); + } + + return hashes; +} + +static CollisionStats count_collisions(const std::vector &hashes, unsigned bits) +{ + std::unordered_set seen; + seen.reserve(hashes.size() * 2); + + const uint64_t mask = bit_mask(bits); + for (uint64_t hash : hashes) { + seen.insert(hash & mask); + } + + return {hashes.size() - seen.size(), seen.size()}; +} + +int main(int argc, char **argv) +{ + const int runs = argc > 1 ? std::max(1, std::atoi(argv[1])) : 5; + const size_t samples = argc > 2 ? std::max(1, std::atoi(argv[2])) : 50000; + + const std::vector lengths = {1, 4, 8, 16, 32, 64, 128, 256}; + const std::vector bit_widths = {10, 12, 16, 20, 24, 32}; + const std::vector hashes = { + {"xxh32", hash_xxh32}, + {"xxh64", hash_xxh64}, + {"xxh3_64", hash_xxh3_64}, + {"city32", hash_city32}, + {"city64", hash_city64}, + {"joaat", hash_joaat}, + }; + + const fs::path out_dir = fs::path(__FILE__).stem(); + fs::create_directories(out_dir); + + for (const HashCase &hash : hashes) { + const fs::path out_path = out_dir / (std::string(hash.name) + ".out"); + std::ofstream out(out_path); + if (!out) { + std::cerr << "failed to open " << out_path << '\n'; + return 1; + } + + out << "hash,length,bits,samples,runs,alphabet,median_collisions,median_collision_rate,median_unique\n"; + out << std::fixed << std::setprecision(8); + + for (size_t len : lengths) { + std::vector> run_hashes; + run_hashes.reserve(runs); + + for (int run = 0; run < runs; ++run) { + const uint64_t seed = 0x415253565f617363ULL ^ (len << 8) ^ run; + run_hashes.push_back(random_hashes(hash.fn, len, samples, seed)); + } + + for (unsigned bits : bit_widths) { + std::vector collision_values; + std::vector unique_values; + collision_values.reserve(runs); + unique_values.reserve(runs); + + for (const auto &hashes_for_run : run_hashes) { + const CollisionStats stats = count_collisions(hashes_for_run, bits); + collision_values.push_back(static_cast(stats.collisions)); + unique_values.push_back(static_cast(stats.unique)); + } + + const double median_collisions = median(collision_values); + const double median_unique = median(unique_values); + out << hash.name << ',' + << len << ',' + << bits << ',' + << samples << ',' + << runs << ',' + << "a-zA-Z" << ',' + << median_collisions << ',' + << (median_collisions / static_cast(samples)) << ',' + << median_unique << '\n'; + } + } + } + + std::cerr << "wrote " << out_dir << "/*.out\n"; + return 0; +} diff --git a/hash_testing/collizions_ascii/city32.out b/hash_testing/collizions_ascii/city32.out new file mode 100644 index 0000000..7fcfe3f --- /dev/null +++ b/hash_testing/collizions_ascii/city32.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,alphabet,median_collisions,median_collision_rate,median_unique +city32,1,10,1000,3,a-zA-Z,950.00000000,0.95000000,50.00000000 +city32,1,12,1000,3,a-zA-Z,949.00000000,0.94900000,51.00000000 +city32,1,16,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city32,1,20,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city32,1,24,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city32,1,32,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city32,4,10,1000,3,a-zA-Z,360.00000000,0.36000000,640.00000000 +city32,4,12,1000,3,a-zA-Z,104.00000000,0.10400000,896.00000000 +city32,4,16,1000,3,a-zA-Z,8.00000000,0.00800000,992.00000000 +city32,4,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,4,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,4,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,8,10,1000,3,a-zA-Z,362.00000000,0.36200000,638.00000000 +city32,8,12,1000,3,a-zA-Z,114.00000000,0.11400000,886.00000000 +city32,8,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +city32,8,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +city32,8,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,8,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,16,10,1000,3,a-zA-Z,359.00000000,0.35900000,641.00000000 +city32,16,12,1000,3,a-zA-Z,114.00000000,0.11400000,886.00000000 +city32,16,16,1000,3,a-zA-Z,5.00000000,0.00500000,995.00000000 +city32,16,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,16,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,16,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,32,10,1000,3,a-zA-Z,364.00000000,0.36400000,636.00000000 +city32,32,12,1000,3,a-zA-Z,119.00000000,0.11900000,881.00000000 +city32,32,16,1000,3,a-zA-Z,8.00000000,0.00800000,992.00000000 +city32,32,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +city32,32,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,32,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,64,10,1000,3,a-zA-Z,361.00000000,0.36100000,639.00000000 +city32,64,12,1000,3,a-zA-Z,113.00000000,0.11300000,887.00000000 +city32,64,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +city32,64,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,64,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,64,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,128,10,1000,3,a-zA-Z,365.00000000,0.36500000,635.00000000 +city32,128,12,1000,3,a-zA-Z,105.00000000,0.10500000,895.00000000 +city32,128,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +city32,128,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,128,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,128,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,256,10,1000,3,a-zA-Z,367.00000000,0.36700000,633.00000000 +city32,256,12,1000,3,a-zA-Z,125.00000000,0.12500000,875.00000000 +city32,256,16,1000,3,a-zA-Z,10.00000000,0.01000000,990.00000000 +city32,256,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,256,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city32,256,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions_ascii/city64.out b/hash_testing/collizions_ascii/city64.out new file mode 100644 index 0000000..462c122 --- /dev/null +++ b/hash_testing/collizions_ascii/city64.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,alphabet,median_collisions,median_collision_rate,median_unique +city64,1,10,1000,3,a-zA-Z,949.00000000,0.94900000,51.00000000 +city64,1,12,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city64,1,16,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city64,1,20,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city64,1,24,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city64,1,32,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +city64,4,10,1000,3,a-zA-Z,371.00000000,0.37100000,629.00000000 +city64,4,12,1000,3,a-zA-Z,113.00000000,0.11300000,887.00000000 +city64,4,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +city64,4,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,4,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,4,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,8,10,1000,3,a-zA-Z,366.00000000,0.36600000,634.00000000 +city64,8,12,1000,3,a-zA-Z,116.00000000,0.11600000,884.00000000 +city64,8,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +city64,8,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +city64,8,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,8,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,16,10,1000,3,a-zA-Z,353.00000000,0.35300000,647.00000000 +city64,16,12,1000,3,a-zA-Z,116.00000000,0.11600000,884.00000000 +city64,16,16,1000,3,a-zA-Z,5.00000000,0.00500000,995.00000000 +city64,16,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,16,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,16,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,32,10,1000,3,a-zA-Z,349.00000000,0.34900000,651.00000000 +city64,32,12,1000,3,a-zA-Z,116.00000000,0.11600000,884.00000000 +city64,32,16,1000,3,a-zA-Z,5.00000000,0.00500000,995.00000000 +city64,32,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,32,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,32,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,64,10,1000,3,a-zA-Z,351.00000000,0.35100000,649.00000000 +city64,64,12,1000,3,a-zA-Z,107.00000000,0.10700000,893.00000000 +city64,64,16,1000,3,a-zA-Z,7.00000000,0.00700000,993.00000000 +city64,64,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,64,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,64,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,128,10,1000,3,a-zA-Z,348.00000000,0.34800000,652.00000000 +city64,128,12,1000,3,a-zA-Z,106.00000000,0.10600000,894.00000000 +city64,128,16,1000,3,a-zA-Z,7.00000000,0.00700000,993.00000000 +city64,128,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +city64,128,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,128,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,256,10,1000,3,a-zA-Z,360.00000000,0.36000000,640.00000000 +city64,256,12,1000,3,a-zA-Z,114.00000000,0.11400000,886.00000000 +city64,256,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +city64,256,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,256,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +city64,256,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions_ascii/joaat.out b/hash_testing/collizions_ascii/joaat.out new file mode 100644 index 0000000..8249e83 --- /dev/null +++ b/hash_testing/collizions_ascii/joaat.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,alphabet,median_collisions,median_collision_rate,median_unique +joaat,1,10,1000,3,a-zA-Z,950.00000000,0.95000000,50.00000000 +joaat,1,12,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +joaat,1,16,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +joaat,1,20,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +joaat,1,24,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +joaat,1,32,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +joaat,4,10,1000,3,a-zA-Z,371.00000000,0.37100000,629.00000000 +joaat,4,12,1000,3,a-zA-Z,115.00000000,0.11500000,885.00000000 +joaat,4,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +joaat,4,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +joaat,4,24,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +joaat,4,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,8,10,1000,3,a-zA-Z,359.00000000,0.35900000,641.00000000 +joaat,8,12,1000,3,a-zA-Z,118.00000000,0.11800000,882.00000000 +joaat,8,16,1000,3,a-zA-Z,5.00000000,0.00500000,995.00000000 +joaat,8,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,8,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,8,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,16,10,1000,3,a-zA-Z,369.00000000,0.36900000,631.00000000 +joaat,16,12,1000,3,a-zA-Z,114.00000000,0.11400000,886.00000000 +joaat,16,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +joaat,16,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +joaat,16,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,16,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,32,10,1000,3,a-zA-Z,360.00000000,0.36000000,640.00000000 +joaat,32,12,1000,3,a-zA-Z,113.00000000,0.11300000,887.00000000 +joaat,32,16,1000,3,a-zA-Z,7.00000000,0.00700000,993.00000000 +joaat,32,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,32,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,32,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,64,10,1000,3,a-zA-Z,367.00000000,0.36700000,633.00000000 +joaat,64,12,1000,3,a-zA-Z,113.00000000,0.11300000,887.00000000 +joaat,64,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +joaat,64,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +joaat,64,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,64,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,128,10,1000,3,a-zA-Z,361.00000000,0.36100000,639.00000000 +joaat,128,12,1000,3,a-zA-Z,111.00000000,0.11100000,889.00000000 +joaat,128,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +joaat,128,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,128,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,128,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,256,10,1000,3,a-zA-Z,365.00000000,0.36500000,635.00000000 +joaat,256,12,1000,3,a-zA-Z,124.00000000,0.12400000,876.00000000 +joaat,256,16,1000,3,a-zA-Z,8.00000000,0.00800000,992.00000000 +joaat,256,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,256,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +joaat,256,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions_ascii/xxh32.out b/hash_testing/collizions_ascii/xxh32.out new file mode 100644 index 0000000..5ea184b --- /dev/null +++ b/hash_testing/collizions_ascii/xxh32.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,alphabet,median_collisions,median_collision_rate,median_unique +xxh32,1,10,1000,3,a-zA-Z,950.00000000,0.95000000,50.00000000 +xxh32,1,12,1000,3,a-zA-Z,949.00000000,0.94900000,51.00000000 +xxh32,1,16,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh32,1,20,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh32,1,24,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh32,1,32,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh32,4,10,1000,3,a-zA-Z,349.00000000,0.34900000,651.00000000 +xxh32,4,12,1000,3,a-zA-Z,107.00000000,0.10700000,893.00000000 +xxh32,4,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +xxh32,4,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +xxh32,4,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,4,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,8,10,1000,3,a-zA-Z,359.00000000,0.35900000,641.00000000 +xxh32,8,12,1000,3,a-zA-Z,108.00000000,0.10800000,892.00000000 +xxh32,8,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +xxh32,8,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,8,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,8,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,16,10,1000,3,a-zA-Z,356.00000000,0.35600000,644.00000000 +xxh32,16,12,1000,3,a-zA-Z,119.00000000,0.11900000,881.00000000 +xxh32,16,16,1000,3,a-zA-Z,8.00000000,0.00800000,992.00000000 +xxh32,16,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,16,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,16,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,32,10,1000,3,a-zA-Z,364.00000000,0.36400000,636.00000000 +xxh32,32,12,1000,3,a-zA-Z,105.00000000,0.10500000,895.00000000 +xxh32,32,16,1000,3,a-zA-Z,10.00000000,0.01000000,990.00000000 +xxh32,32,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,32,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,32,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,64,10,1000,3,a-zA-Z,355.00000000,0.35500000,645.00000000 +xxh32,64,12,1000,3,a-zA-Z,112.00000000,0.11200000,888.00000000 +xxh32,64,16,1000,3,a-zA-Z,8.00000000,0.00800000,992.00000000 +xxh32,64,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +xxh32,64,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,64,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,128,10,1000,3,a-zA-Z,359.00000000,0.35900000,641.00000000 +xxh32,128,12,1000,3,a-zA-Z,113.00000000,0.11300000,887.00000000 +xxh32,128,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +xxh32,128,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,128,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,128,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,256,10,1000,3,a-zA-Z,360.00000000,0.36000000,640.00000000 +xxh32,256,12,1000,3,a-zA-Z,117.00000000,0.11700000,883.00000000 +xxh32,256,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +xxh32,256,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,256,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh32,256,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions_ascii/xxh3_64.out b/hash_testing/collizions_ascii/xxh3_64.out new file mode 100644 index 0000000..e0ffba9 --- /dev/null +++ b/hash_testing/collizions_ascii/xxh3_64.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,alphabet,median_collisions,median_collision_rate,median_unique +xxh3_64,1,10,1000,3,a-zA-Z,949.00000000,0.94900000,51.00000000 +xxh3_64,1,12,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh3_64,1,16,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh3_64,1,20,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh3_64,1,24,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh3_64,1,32,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh3_64,4,10,1000,3,a-zA-Z,359.00000000,0.35900000,641.00000000 +xxh3_64,4,12,1000,3,a-zA-Z,109.00000000,0.10900000,891.00000000 +xxh3_64,4,16,1000,3,a-zA-Z,10.00000000,0.01000000,990.00000000 +xxh3_64,4,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +xxh3_64,4,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,4,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,8,10,1000,3,a-zA-Z,353.00000000,0.35300000,647.00000000 +xxh3_64,8,12,1000,3,a-zA-Z,107.00000000,0.10700000,893.00000000 +xxh3_64,8,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +xxh3_64,8,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,8,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,8,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,16,10,1000,3,a-zA-Z,353.00000000,0.35300000,647.00000000 +xxh3_64,16,12,1000,3,a-zA-Z,107.00000000,0.10700000,893.00000000 +xxh3_64,16,16,1000,3,a-zA-Z,7.00000000,0.00700000,993.00000000 +xxh3_64,16,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,16,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,16,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,32,10,1000,3,a-zA-Z,352.00000000,0.35200000,648.00000000 +xxh3_64,32,12,1000,3,a-zA-Z,109.00000000,0.10900000,891.00000000 +xxh3_64,32,16,1000,3,a-zA-Z,10.00000000,0.01000000,990.00000000 +xxh3_64,32,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,32,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,32,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,64,10,1000,3,a-zA-Z,344.00000000,0.34400000,656.00000000 +xxh3_64,64,12,1000,3,a-zA-Z,103.00000000,0.10300000,897.00000000 +xxh3_64,64,16,1000,3,a-zA-Z,6.00000000,0.00600000,994.00000000 +xxh3_64,64,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +xxh3_64,64,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,64,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,128,10,1000,3,a-zA-Z,361.00000000,0.36100000,639.00000000 +xxh3_64,128,12,1000,3,a-zA-Z,115.00000000,0.11500000,885.00000000 +xxh3_64,128,16,1000,3,a-zA-Z,7.00000000,0.00700000,993.00000000 +xxh3_64,128,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +xxh3_64,128,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,128,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,256,10,1000,3,a-zA-Z,354.00000000,0.35400000,646.00000000 +xxh3_64,256,12,1000,3,a-zA-Z,116.00000000,0.11600000,884.00000000 +xxh3_64,256,16,1000,3,a-zA-Z,4.00000000,0.00400000,996.00000000 +xxh3_64,256,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,256,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh3_64,256,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/collizions_ascii/xxh64.out b/hash_testing/collizions_ascii/xxh64.out new file mode 100644 index 0000000..b74667e --- /dev/null +++ b/hash_testing/collizions_ascii/xxh64.out @@ -0,0 +1,49 @@ +hash,length,bits,samples,runs,alphabet,median_collisions,median_collision_rate,median_unique +xxh64,1,10,1000,3,a-zA-Z,950.00000000,0.95000000,50.00000000 +xxh64,1,12,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh64,1,16,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh64,1,20,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh64,1,24,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh64,1,32,1000,3,a-zA-Z,948.00000000,0.94800000,52.00000000 +xxh64,4,10,1000,3,a-zA-Z,356.00000000,0.35600000,644.00000000 +xxh64,4,12,1000,3,a-zA-Z,115.00000000,0.11500000,885.00000000 +xxh64,4,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +xxh64,4,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +xxh64,4,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,4,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,8,10,1000,3,a-zA-Z,356.00000000,0.35600000,644.00000000 +xxh64,8,12,1000,3,a-zA-Z,100.00000000,0.10000000,900.00000000 +xxh64,8,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +xxh64,8,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +xxh64,8,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,8,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,16,10,1000,3,a-zA-Z,364.00000000,0.36400000,636.00000000 +xxh64,16,12,1000,3,a-zA-Z,115.00000000,0.11500000,885.00000000 +xxh64,16,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +xxh64,16,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,16,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,16,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,32,10,1000,3,a-zA-Z,367.00000000,0.36700000,633.00000000 +xxh64,32,12,1000,3,a-zA-Z,108.00000000,0.10800000,892.00000000 +xxh64,32,16,1000,3,a-zA-Z,5.00000000,0.00500000,995.00000000 +xxh64,32,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,32,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,32,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,64,10,1000,3,a-zA-Z,366.00000000,0.36600000,634.00000000 +xxh64,64,12,1000,3,a-zA-Z,113.00000000,0.11300000,887.00000000 +xxh64,64,16,1000,3,a-zA-Z,9.00000000,0.00900000,991.00000000 +xxh64,64,20,1000,3,a-zA-Z,1.00000000,0.00100000,999.00000000 +xxh64,64,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,64,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,128,10,1000,3,a-zA-Z,356.00000000,0.35600000,644.00000000 +xxh64,128,12,1000,3,a-zA-Z,106.00000000,0.10600000,894.00000000 +xxh64,128,16,1000,3,a-zA-Z,5.00000000,0.00500000,995.00000000 +xxh64,128,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,128,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,128,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,256,10,1000,3,a-zA-Z,363.00000000,0.36300000,637.00000000 +xxh64,256,12,1000,3,a-zA-Z,116.00000000,0.11600000,884.00000000 +xxh64,256,16,1000,3,a-zA-Z,8.00000000,0.00800000,992.00000000 +xxh64,256,20,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,256,24,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 +xxh64,256,32,1000,3,a-zA-Z,0.00000000,0.00000000,1000.00000000 diff --git a/hash_testing/graphs.py b/hash_testing/graphs.py new file mode 100644 index 0000000..9e81704 --- /dev/null +++ b/hash_testing/graphs.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python3 +"""Convert hash benchmark CSV outputs into SVG graphs. + +Input directories: + speed/*.out + collizions/*.out + collizions_ascii/*.out + +Output: + graphs/speed.svg + graphs/collizions.svg + graphs/collizions_ascii.svg +""" + +from __future__ import annotations + +import csv +import html +import math +from collections import defaultdict +from pathlib import Path +from typing import Callable, Iterable + +ROOT = Path(__file__).resolve().parent +GRAPH_DIR = ROOT / "graphs" +HASH_ORDER = ["xxh32", "xxh64", "xxh3_64", "city32", "city64", "joaat"] +COLORS = { + "xxh32": "#1f77b4", + "xxh64": "#ff7f0e", + "xxh3_64": "#2ca02c", + "city32": "#d62728", + "city64": "#9467bd", + "joaat": "#8c564b", +} + + +def read_rows(test_name: str) -> list[dict[str, str]]: + rows: list[dict[str, str]] = [] + for path in sorted((ROOT / test_name).glob("*.out")): + with path.open(newline="") as f: + rows.extend(csv.DictReader(f)) + if not rows: + raise FileNotFoundError(f"no .out files found in {ROOT / test_name}") + return rows + + +def log_scale(values: Iterable[float], lo_px: float, hi_px: float) -> Callable[[float], float]: + vals = [v for v in values if v > 0] + lo = min(vals) + hi = max(vals) + if lo == hi: + return lambda _v: (lo_px + hi_px) / 2.0 + log_lo = math.log10(lo) + log_hi = math.log10(hi) + return lambda v: lo_px + (math.log10(max(v, lo)) - log_lo) / (log_hi - log_lo) * (hi_px - lo_px) + + +def linear_scale(values: Iterable[float], lo_px: float, hi_px: float) -> Callable[[float], float]: + vals = list(values) + lo = min(vals) + hi = max(vals) + if lo == hi: + return lambda _v: (lo_px + hi_px) / 2.0 + return lambda v: lo_px + (v - lo) / (hi - lo) * (hi_px - lo_px) + + +def nice_ticks(max_value: float, count: int = 5) -> list[float]: + if max_value <= 0: + return [0.0] + raw = max_value / max(count - 1, 1) + power = 10 ** math.floor(math.log10(raw)) + step = min((1, 2, 5, 10), key=lambda x: abs(x * power - raw)) * power + ticks = [0.0] + value = step + while value <= max_value * 1.001: + ticks.append(value) + value += step + return ticks + + +def fmt_num(value: float) -> str: + if value == 0: + return "0" + if abs(value) < 0.01 or abs(value) >= 10000: + return f"{value:.2e}" + if abs(value) < 1: + return f"{value:.4f}".rstrip("0").rstrip(".") + return f"{value:.2f}".rstrip("0").rstrip(".") + + +def polyline(points: list[tuple[float, float]], color: str) -> str: + pts = " ".join(f"{x:.2f},{y:.2f}" for x, y in points) + circles = "".join( + f'' + for x, y in points + ) + return ( + f'{circles}' + ) + + +def legend(x: int, y: int) -> str: + parts = [] + for i, name in enumerate(HASH_ORDER): + yy = y + i * 18 + color = COLORS[name] + parts.append(f'') + parts.append(f'{html.escape(name)}') + return "\n".join(parts) + + +def chart( + *, + title: str, + series: dict[str, list[tuple[float, float]]], + x_label: str, + y_label: str, + width: int, + height: int, + x_log: bool = True, +) -> str: + margin_l, margin_r, margin_t, margin_b = 72, 150, 42, 58 + plot_x0, plot_x1 = margin_l, width - margin_r + plot_y0, plot_y1 = margin_t, height - margin_b + + all_points = [pt for points in series.values() for pt in points] + xs = [x for x, _ in all_points] + ys = [y for _, y in all_points] + x_map = log_scale(xs, plot_x0, plot_x1) if x_log else linear_scale(xs, plot_x0, plot_x1) + y_max = max(ys) if ys else 1.0 + y_map_linear = linear_scale([0.0, y_max], plot_y1, plot_y0) + + parts = [ + f'', + f'{html.escape(title)}', + f'', + ] + + x_ticks = sorted(set(xs)) + for x in x_ticks: + px = x_map(x) + parts.append(f'') + parts.append(f'{fmt_num(x)}') + + for y in nice_ticks(y_max): + py = y_map_linear(y) + parts.append(f'') + parts.append(f'{fmt_num(y)}') + + parts.append(f'') + parts.append(f'') + parts.append(f'{html.escape(x_label)}') + parts.append(f'{html.escape(y_label)}') + + for name in HASH_ORDER: + points = series.get(name, []) + if not points: + continue + mapped = [(x_map(x), y_map_linear(y)) for x, y in sorted(points)] + parts.append(polyline(mapped, COLORS[name])) + + parts.append(legend(width - margin_r + 26, margin_t + 16)) + parts.append("") + return "\n".join(parts) + + +def svg_page(width: int, height: int, body: str) -> str: + return f''' + + +{body} + +''' + + +def make_speed() -> None: + rows = read_rows("speed") + series: dict[str, list[tuple[float, float]]] = defaultdict(list) + for row in rows: + series[row["hash"]].append((float(row["length"]), float(row["median_gib_per_s"]))) + + body = chart( + title="Hash speed on random bytes (median GiB/s)", + series=series, + x_label="input length, bytes (log scale)", + y_label="median GiB/s", + width=1100, + height=620, + ) + (GRAPH_DIR / "speed.svg").write_text(svg_page(1100, 620, body)) + + +def collision_series(rows: list[dict[str, str]], bits: int) -> dict[str, list[tuple[float, float]]]: + series: dict[str, list[tuple[float, float]]] = defaultdict(list) + for row in rows: + length = float(row["length"]) + if length == 1: + continue + if int(row["bits"]) == bits: + series[row["hash"]].append((length, float(row["median_collision_rate"]))) + return series + + +def make_collision(test_name: str, title_prefix: str) -> None: + rows = read_rows(test_name) + bits_values = sorted({int(row["bits"]) for row in rows}) + chart_w, chart_h = 1100, 420 + body_parts = [] + for i, bits in enumerate(bits_values): + sub = chart( + title=f"{title_prefix}: {bits}-bit truncated hash collision rate", + series=collision_series(rows, bits), + x_label="input length, bytes/chars (log scale)", + y_label="median collision rate", + width=chart_w, + height=chart_h, + ) + body_parts.append(f'{sub}') + + height = chart_h * len(bits_values) + (GRAPH_DIR / f"{test_name}.svg").write_text(svg_page(chart_w, height, "\n".join(body_parts))) + + +def main() -> int: + GRAPH_DIR.mkdir(exist_ok=True) + make_speed() + make_collision("collizions", "Random bytes") + make_collision("collizions_ascii", "Random a-zA-Z strings") + print(f"wrote {GRAPH_DIR / 'speed.svg'}") + print(f"wrote {GRAPH_DIR / 'collizions.svg'}") + print(f"wrote {GRAPH_DIR / 'collizions_ascii.svg'}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/hash_testing/graphs/collizions.svg b/hash_testing/graphs/collizions.svg new file mode 100644 index 0000000..8f5a46e --- /dev/null +++ b/hash_testing/graphs/collizions.svg @@ -0,0 +1,304 @@ + + + + +Random bytes: 10-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +0.1 + +0.2 + +0.3 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random bytes: 12-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +0.02 + +0.04 + +0.06 + +0.08 + +0.1 + +0.12 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random bytes: 16-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +2.00e-03 + +4.00e-03 + +6.00e-03 + +8.00e-03 + +0.01 + +0.012 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random bytes: 20-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +2.00e-04 + +4.00e-04 + +6.00e-04 + +8.00e-04 + +1.00e-03 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random bytes: 24-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random bytes: 32-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + diff --git a/hash_testing/graphs/collizions_ascii.svg b/hash_testing/graphs/collizions_ascii.svg new file mode 100644 index 0000000..612a848 --- /dev/null +++ b/hash_testing/graphs/collizions_ascii.svg @@ -0,0 +1,312 @@ + + + + +Random a-zA-Z strings: 10-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +0.1 + +0.2 + +0.3 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random a-zA-Z strings: 12-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +0.02 + +0.04 + +0.06 + +0.08 + +0.1 + +0.12 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random a-zA-Z strings: 16-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +2.00e-03 + +4.00e-03 + +6.00e-03 + +8.00e-03 + +0.01 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random a-zA-Z strings: 20-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +2.00e-04 + +4.00e-04 + +6.00e-04 + +8.00e-04 + +1.00e-03 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random a-zA-Z strings: 24-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + +2.00e-04 + +4.00e-04 + +6.00e-04 + +8.00e-04 + +1.00e-03 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + +Random a-zA-Z strings: 32-bit truncated hash collision rate + + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +0 + + +input length, bytes/chars (log scale) +median collision rate + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + diff --git a/hash_testing/graphs/speed.svg b/hash_testing/graphs/speed.svg new file mode 100644 index 0000000..6cc4c40 --- /dev/null +++ b/hash_testing/graphs/speed.svg @@ -0,0 +1,72 @@ + + + + +Hash speed on random bytes (median GiB/s) + + +1 + +4 + +8 + +16 + +32 + +64 + +128 + +256 + +1024 + +4096 + +1.64e+04 + +6.55e+04 + +1.05e+06 + +0 + +5 + +10 + +15 + + +input length, bytes (log scale) +median GiB/s + + + + + + + +xxh32 + +xxh64 + +xxh3_64 + +city32 + +city64 + +joaat + + diff --git a/hash_testing/speed.cpp b/hash_testing/speed.cpp new file mode 100644 index 0000000..da7c8dd --- /dev/null +++ b/hash_testing/speed.cpp @@ -0,0 +1,192 @@ +/* +Compare speed of hash functions on fixed random byte strings. + +Output: speed/{hash_name}.out, CSV, one row per input length. + +Build example: + cc -O3 -I. -c src/joaat/hash.c -o joaat.o + cc -O3 -I. -c src/xxHash/xxhash.c -o xxhash.o + g++ -O3 -std=c++17 -I. -Isrc/cityhash/src speed.cpp \ + src/cityhash/src/city.cc joaat.o xxhash.o -o speed_test + +Run: + ./speed_test [runs=7] [target_mib_per_run=32] [max_iters=200000] +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/cityhash/src/city.h" +#include "src/joaat/hash.h" +#include "src/xxHash/xxhash.h" + +namespace fs = std::filesystem; + +using Clock = std::chrono::steady_clock; +using HashFn = uint64_t (*)(const void *, size_t); + +struct HashCase { + std::string_view name; + HashFn fn; +}; + +static uint64_t hash_xxh32(const void *data, size_t len) +{ + return XXH32(data, len, 0); +} + +static uint64_t hash_xxh64(const void *data, size_t len) +{ + return XXH64(data, len, 0); +} + +static uint64_t hash_xxh3_64(const void *data, size_t len) +{ + return XXH3_64bits(data, len); +} + +static uint64_t hash_city32(const void *data, size_t len) +{ + return CityHash32(static_cast(data), len); +} + +static uint64_t hash_city64(const void *data, size_t len) +{ + return CityHash64(static_cast(data), len); +} + +static uint64_t hash_joaat(const void *data, size_t len) +{ + return joaat_hash_bytes(data, len); +} + +static size_t iterations_for(size_t len, size_t target_bytes, size_t max_iters) +{ + if (len == 0) { + return max_iters; + } + + size_t iters = target_bytes / len; + iters = std::max(iters, 128); + iters = std::min(iters, max_iters); + return iters; +} + +static double median(std::vector values) +{ + const size_t mid = values.size() / 2; + std::nth_element(values.begin(), values.begin() + mid, values.end()); + if (values.size() % 2 != 0) { + return values[mid]; + } + + const double hi = values[mid]; + std::nth_element(values.begin(), values.begin() + mid - 1, values.end()); + return (values[mid - 1] + hi) / 2.0; +} + +static std::vector random_bytes(size_t len) +{ + std::vector data(len); + std::mt19937_64 rng(0x415253565f686173ULL ^ len); + for (unsigned char &byte : data) { + byte = static_cast(rng() & 0xffu); + } + return data; +} + +static uint64_t bench_once(HashFn fn, const std::vector &data, size_t iters) +{ + uint64_t sink = 0; + const void *ptr = data.data(); + const size_t len = data.size(); + + for (size_t i = 0; i < iters; ++i) { + sink ^= fn(ptr, len) + 0x9e3779b97f4a7c15ULL + (sink << 6) + (sink >> 2); + } + + return sink; +} + +int main(int argc, char **argv) +{ + const int runs = argc > 1 ? std::max(1, std::atoi(argv[1])) : 7; + const size_t target_mib = argc > 2 ? std::max(1, std::atoi(argv[2])) : 32; + const size_t max_iters = argc > 3 ? std::max(1, std::atoi(argv[3])) : 200000; + const size_t target_bytes = target_mib * 1024ULL * 1024ULL; + + const std::vector lengths = { + 1, 4, 8, 16, 32, 64, 128, 256, 1024, 4096, 16384, 65536, 1048576, + }; + + const std::vector hashes = { + {"xxh32", hash_xxh32}, + {"xxh64", hash_xxh64}, + {"xxh3_64", hash_xxh3_64}, + {"city32", hash_city32}, + {"city64", hash_city64}, + {"joaat", hash_joaat}, + }; + + const fs::path out_dir = fs::path(__FILE__).stem(); + fs::create_directories(out_dir); + + volatile uint64_t global_sink = 0; + + for (const HashCase &hash : hashes) { + const fs::path out_path = out_dir / (std::string(hash.name) + ".out"); + std::ofstream out(out_path); + if (!out) { + std::cerr << "failed to open " << out_path << '\n'; + return 1; + } + + out << "hash,length,median_ns_per_hash,median_gib_per_s,iterations,runs,total_bytes_per_run,sink\n"; + out << std::fixed << std::setprecision(6); + + for (size_t len : lengths) { + const std::vector data = random_bytes(len); + const size_t iters = iterations_for(len, target_bytes, max_iters); + std::vector ns_per_hash; + std::vector gib_per_s; + uint64_t sink = 0; + + /* Warmup outside measured runs. */ + sink ^= bench_once(hash.fn, data, std::min(iters, 1024)); + + for (int run = 0; run < runs; ++run) { + const auto start = Clock::now(); + sink ^= bench_once(hash.fn, data, iters); + const auto stop = Clock::now(); + + const double seconds = std::chrono::duration(stop - start).count(); + const double bytes = static_cast(len) * static_cast(iters); + ns_per_hash.push_back(seconds * 1e9 / static_cast(iters)); + gib_per_s.push_back(bytes / seconds / (1024.0 * 1024.0 * 1024.0)); + } + + global_sink ^= sink; + out << hash.name << ',' + << len << ',' + << median(ns_per_hash) << ',' + << median(gib_per_s) << ',' + << iters << ',' + << runs << ',' + << (len * iters) << ',' + << sink << '\n'; + } + } + + std::cerr << "wrote " << out_dir << "/*.out; sink=" << global_sink << '\n'; + return 0; +} diff --git a/hash_testing/speed/city32.out b/hash_testing/speed/city32.out new file mode 100644 index 0000000..a3a5236 --- /dev/null +++ b/hash_testing/speed/city32.out @@ -0,0 +1,14 @@ +hash,length,median_ns_per_hash,median_gib_per_s,iterations,runs,total_bytes_per_run,sink +city32,1,6.582800,0.141478,5000,3,5000,16674745115447896877 +city32,4,8.617000,0.432319,5000,3,20000,6834968359130584710 +city32,8,7.778200,0.957880,5000,3,40000,17928596561067382596 +city32,16,10.401800,1.432556,5000,3,80000,585249989458250422 +city32,32,16.704600,1.784079,5000,3,160000,13787592663029129514 +city32,64,25.604600,2.327888,5000,3,320000,12623932612374253897 +city32,128,37.818000,3.152184,5000,3,640000,4754174121514289686 +city32,256,62.812012,3.795748,4096,3,1048576,13269564425911742485 +city32,1024,232.597656,4.100103,1024,3,1048576,0 +city32,4096,862.441406,4.423138,256,3,1048576,0 +city32,16384,3454.429688,4.417166,128,3,2097152,0 +city32,65536,14406.171875,4.236737,128,3,8388608,0 +city32,1048576,227040.421875,4.301272,128,3,134217728,0 diff --git a/hash_testing/speed/city64.out b/hash_testing/speed/city64.out new file mode 100644 index 0000000..cbf7ede --- /dev/null +++ b/hash_testing/speed/city64.out @@ -0,0 +1,14 @@ +hash,length,median_ns_per_hash,median_gib_per_s,iterations,runs,total_bytes_per_run,sink +city64,1,4.665800,0.199606,5000,3,5000,8474056804404152685 +city64,4,3.948400,0.943494,5000,3,20000,10023783907389256147 +city64,8,4.316600,1.726030,5000,3,40000,4923132165090664747 +city64,16,4.309000,3.458148,5000,3,80000,1662106133930722968 +city64,32,4.447000,6.701669,5000,3,160000,9249275520485373389 +city64,64,8.549400,6.971793,5000,3,320000,8829126626941822998 +city64,128,18.306000,6.512034,5000,3,640000,5226008620245186912 +city64,256,28.666504,8.316974,4096,3,1048576,8826952754360476649 +city64,1024,90.090820,10.585699,1024,3,1048576,0 +city64,4096,337.535156,11.301629,256,3,1048576,0 +city64,16384,1359.195312,11.226340,128,3,2097152,0 +city64,65536,6198.054688,9.847470,128,3,8388608,0 +city64,1048576,101876.867188,9.585714,128,3,134217728,0 diff --git a/hash_testing/speed/joaat.out b/hash_testing/speed/joaat.out new file mode 100644 index 0000000..7c4c557 --- /dev/null +++ b/hash_testing/speed/joaat.out @@ -0,0 +1,14 @@ +hash,length,median_ns_per_hash,median_gib_per_s,iterations,runs,total_bytes_per_run,sink +joaat,1,4.318800,0.215644,5000,3,5000,9861566666569931081 +joaat,4,6.811400,0.546920,5000,3,20000,15617170004321863919 +joaat,8,10.816200,0.688835,5000,3,40000,8389904457286630203 +joaat,16,22.330000,0.667316,5000,3,80000,16051409265879503700 +joaat,32,50.984600,0.584536,5000,3,160000,11337794564698630681 +joaat,64,112.921200,0.527843,5000,3,320000,8235683922580474959 +joaat,128,223.239800,0.533997,5000,3,640000,2816532755007693299 +joaat,256,439.203125,0.542844,4096,3,1048576,9523086540095906696 +joaat,1024,1796.485352,0.530856,1024,3,1048576,0 +joaat,4096,7143.164062,0.534035,256,3,1048576,0 +joaat,16384,27309.882812,0.558728,128,3,2097152,0 +joaat,65536,112571.984375,0.542188,128,3,8388608,0 +joaat,1048576,1811796.007812,0.539002,128,3,134217728,0 diff --git a/hash_testing/speed/xxh32.out b/hash_testing/speed/xxh32.out new file mode 100644 index 0000000..d0f99d1 --- /dev/null +++ b/hash_testing/speed/xxh32.out @@ -0,0 +1,14 @@ +hash,length,median_ns_per_hash,median_gib_per_s,iterations,runs,total_bytes_per_run,sink +xxh32,1,4.854600,0.191843,5000,3,5000,6522654199044435553 +xxh32,4,5.032800,0.740202,5000,3,20000,10894883772763203962 +xxh32,8,5.434400,1.371003,5000,3,40000,17492032097546716743 +xxh32,16,7.791800,1.912416,5000,3,80000,16509346400352003235 +xxh32,32,11.561800,2.577654,5000,3,160000,3483195499313451367 +xxh32,64,15.825000,3.766486,5000,3,320000,9266912307262829024 +xxh32,128,31.086600,3.834748,5000,3,640000,10535856100608339296 +xxh32,256,51.642334,4.616727,4096,3,1048576,10382063883164162779 +xxh32,1024,184.234375,5.176419,1024,3,1048576,0 +xxh32,4096,720.960938,5.291129,256,3,1048576,0 +xxh32,16384,2899.031250,5.263410,128,3,2097152,0 +xxh32,65536,15237.203125,4.005667,128,3,8388608,0 +xxh32,1048576,216434.320312,4.512050,128,3,134217728,0 diff --git a/hash_testing/speed/xxh3_64.out b/hash_testing/speed/xxh3_64.out new file mode 100644 index 0000000..6f04269 --- /dev/null +++ b/hash_testing/speed/xxh3_64.out @@ -0,0 +1,14 @@ +hash,length,median_ns_per_hash,median_gib_per_s,iterations,runs,total_bytes_per_run,sink +xxh3_64,1,5.566200,0.167317,5000,3,5000,7310567083830705690 +xxh3_64,4,3.946200,0.944020,5000,3,20000,4981814379862673761 +xxh3_64,8,3.947200,1.887561,5000,3,40000,13755310000591908031 +xxh3_64,16,4.304400,3.461844,5000,3,80000,15649559784914910543 +xxh3_64,32,7.166400,4.158618,5000,3,160000,10002708629695263677 +xxh3_64,64,9.560600,6.234404,5000,3,320000,6718927993513098706 +xxh3_64,128,12.897400,9.242893,5000,3,640000,2962501802752218590 +xxh3_64,256,28.443604,8.382151,4096,3,1048576,17853447545775485208 +xxh3_64,1024,69.244141,13.772636,1024,3,1048576,0 +xxh3_64,4096,248.847656,15.329448,256,3,1048576,0 +xxh3_64,16384,969.367188,15.740980,128,3,2097152,0 +xxh3_64,65536,5187.992188,11.764697,128,3,8388608,0 +xxh3_64,1048576,75862.406250,12.872812,128,3,134217728,0 diff --git a/hash_testing/speed/xxh64.out b/hash_testing/speed/xxh64.out new file mode 100644 index 0000000..0025929 --- /dev/null +++ b/hash_testing/speed/xxh64.out @@ -0,0 +1,14 @@ +hash,length,median_ns_per_hash,median_gib_per_s,iterations,runs,total_bytes_per_run,sink +xxh64,1,8.277000,0.112519,5000,3,5000,2399228904051646384 +xxh64,4,9.441800,0.394553,5000,3,20000,15997860383107590433 +xxh64,8,6.452800,1.154628,5000,3,40000,501586348857100055 +xxh64,16,7.537800,1.976858,5000,3,80000,8897080074436808861 +xxh64,32,14.059400,2.119744,5000,3,160000,8152453201417758473 +xxh64,64,17.289600,3.447428,5000,3,320000,5044571514171203936 +xxh64,128,22.666400,5.259295,5000,3,640000,13161812239309679563 +xxh64,256,38.868408,6.133994,4096,3,1048576,1904578271191834218 +xxh64,1024,111.719727,8.536311,1024,3,1048576,0 +xxh64,4096,417.425781,9.138624,256,3,1048576,0 +xxh64,16384,1991.578125,7.661657,128,3,2097152,0 +xxh64,65536,6626.187500,9.211203,128,3,8388608,0 +xxh64,1048576,107473.109375,9.086575,128,3,134217728,0 diff --git a/hash_testing/src/cityhash b/hash_testing/src/cityhash new file mode 160000 index 0000000..f5dc541 --- /dev/null +++ b/hash_testing/src/cityhash @@ -0,0 +1 @@ +Subproject commit f5dc54147fcce12cefd16548c8e760d68ac04226 diff --git a/hash_testing/src/joaat/hash.c b/hash_testing/src/joaat/hash.c new file mode 100644 index 0000000..8f4d280 --- /dev/null +++ b/hash_testing/src/joaat/hash.c @@ -0,0 +1,46 @@ +#include "hash.h" + +#include + +#define JOAAT_SEED 0x9e3779b9u + +uint32_t joaat_hash_bytes(const void *data, size_t len) +{ + uint32_t hash = JOAAT_SEED; + const unsigned char *p = (const unsigned char *)data; + + while (len-- > 0) { + hash += *p++; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash; +} + +uint32_t joaat_hash(const char *str) +{ + uint32_t hash = JOAAT_SEED; + const unsigned char *p = (const unsigned char *)str; + + while (*p) { + hash += *p++; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash; +} + +unsigned int hash(const char *str) +{ + return (unsigned int)joaat_hash(str); +} diff --git a/hash_testing/src/joaat/hash.h b/hash_testing/src/joaat/hash.h new file mode 100644 index 0000000..03c518e --- /dev/null +++ b/hash_testing/src/joaat/hash.h @@ -0,0 +1,21 @@ +#ifndef ARSV_JOAAT_HASH_H +#define ARSV_JOAAT_HASH_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t joaat_hash(const char *str); +uint32_t joaat_hash_bytes(const void *data, size_t len); + +/* Compatibility wrapper matching the original set.c function name. */ +unsigned int hash(const char *str); + +#ifdef __cplusplus +} +#endif + +#endif /* ARSV_JOAAT_HASH_H */ diff --git a/hash_testing/src/xxHash b/hash_testing/src/xxHash new file mode 160000 index 0000000..e573d4d --- /dev/null +++ b/hash_testing/src/xxHash @@ -0,0 +1 @@ +Subproject commit e573d4d2aaeaba0f3e5a0a9a54144a1f2b4b56e7