testing hash

This commit is contained in:
2026-07-02 15:19:31 +03:00
parent ab619909d9
commit 4a1e0bb078
33 changed files with 2356 additions and 0 deletions
+4
View File
@@ -1,5 +1,9 @@
# Notes
## to read
https://www.altlinux.org/Features/Specific
## Hash
в данный момент используется Jenkins OAAT. Считается чуть устаревшим(check), главным аналогом является:
+27
View File
@@ -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 "$@"
+27
View File
@@ -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 "$@"
+27
View File
@@ -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 "$@"
+199
View File
@@ -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 <algorithm>
#include <cstdint>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <random>
#include <string>
#include <string_view>
#include <unordered_set>
#include <vector>
#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<const char *>(data), len);
}
static uint64_t hash_city64(const void *data, size_t len)
{
return CityHash64(static_cast<const char *>(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<double> 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<unsigned char> random_bytes(size_t len, uint64_t seed)
{
std::vector<unsigned char> data(len);
std::mt19937_64 rng(seed);
for (unsigned char &byte : data) {
byte = static_cast<unsigned char>(rng() & 0xffu);
}
return data;
}
static std::vector<uint64_t> random_hashes(HashFn fn, size_t len, size_t samples, uint64_t seed)
{
std::vector<uint64_t> hashes;
hashes.reserve(samples);
std::mt19937_64 seed_rng(seed);
for (size_t i = 0; i < samples; ++i) {
const std::vector<unsigned char> data = random_bytes(len, seed_rng());
hashes.push_back(fn(data.data(), data.size()));
}
return hashes;
}
static CollisionStats count_collisions(const std::vector<uint64_t> &hashes, unsigned bits)
{
std::unordered_set<uint64_t> 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<size_t> lengths = {1, 4, 8, 16, 32, 64, 128, 256};
const std::vector<unsigned> bit_widths = {10, 12, 16, 20, 24, 32};
const std::vector<HashCase> 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<std::vector<uint64_t>> 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<double> collision_values;
std::vector<double> 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<double>(stats.collisions));
unique_values.push_back(static_cast<double>(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<double>(samples)) << ','
<< median_unique << '\n';
}
}
}
std::cerr << "wrote " << out_dir << "/*.out\n";
return 0;
}
+49
View File
@@ -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
+49
View File
@@ -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
+49
View File
@@ -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
+49
View File
@@ -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
+49
View File
@@ -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
+49
View File
@@ -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
+206
View File
@@ -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 <algorithm>
#include <cstdint>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <random>
#include <string>
#include <string_view>
#include <unordered_set>
#include <vector>
#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<const char *>(data), len);
}
static uint64_t hash_city64(const void *data, size_t len)
{
return CityHash64(static_cast<const char *>(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<double> 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<uint64_t> random_hashes(HashFn fn, size_t len, size_t samples, uint64_t seed)
{
std::vector<uint64_t> 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<uint64_t> &hashes, unsigned bits)
{
std::unordered_set<uint64_t> 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<size_t> lengths = {1, 4, 8, 16, 32, 64, 128, 256};
const std::vector<unsigned> bit_widths = {10, 12, 16, 20, 24, 32};
const std::vector<HashCase> 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<std::vector<uint64_t>> 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<double> collision_values;
std::vector<double> 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<double>(stats.collisions));
unique_values.push_back(static_cast<double>(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<double>(samples)) << ','
<< median_unique << '\n';
}
}
}
std::cerr << "wrote " << out_dir << "/*.out\n";
return 0;
}
+49
View File
@@ -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
+49
View File
@@ -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
+49
View File
@@ -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
+49
View File
@@ -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
+49
View File
@@ -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
+49
View File
@@ -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
+245
View File
@@ -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'<circle cx="{x:.2f}" cy="{y:.2f}" r="3" fill="{color}" />'
for x, y in points
)
return (
f'<polyline points="{pts}" fill="none" stroke="{color}" '
f'stroke-width="2" stroke-linejoin="round" stroke-linecap="round" />{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'<rect x="{x}" y="{yy - 10}" width="12" height="12" fill="{color}" />')
parts.append(f'<text x="{x + 18}" y="{yy}" class="legend">{html.escape(name)}</text>')
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'<g class="chart">',
f'<text x="{width / 2:.0f}" y="22" text-anchor="middle" class="title">{html.escape(title)}</text>',
f'<rect x="{plot_x0}" y="{plot_y0}" width="{plot_x1 - plot_x0}" height="{plot_y1 - plot_y0}" class="plot-bg" />',
]
x_ticks = sorted(set(xs))
for x in x_ticks:
px = x_map(x)
parts.append(f'<line x1="{px:.2f}" y1="{plot_y0}" x2="{px:.2f}" y2="{plot_y1}" class="grid" />')
parts.append(f'<text x="{px:.2f}" y="{plot_y1 + 18}" text-anchor="middle" class="tick">{fmt_num(x)}</text>')
for y in nice_ticks(y_max):
py = y_map_linear(y)
parts.append(f'<line x1="{plot_x0}" y1="{py:.2f}" x2="{plot_x1}" y2="{py:.2f}" class="grid" />')
parts.append(f'<text x="{plot_x0 - 8}" y="{py + 4:.2f}" text-anchor="end" class="tick">{fmt_num(y)}</text>')
parts.append(f'<line x1="{plot_x0}" y1="{plot_y1}" x2="{plot_x1}" y2="{plot_y1}" class="axis" />')
parts.append(f'<line x1="{plot_x0}" y1="{plot_y0}" x2="{plot_x0}" y2="{plot_y1}" class="axis" />')
parts.append(f'<text x="{(plot_x0 + plot_x1) / 2:.0f}" y="{height - 14}" text-anchor="middle" class="label">{html.escape(x_label)}</text>')
parts.append(f'<text transform="translate(18,{(plot_y0 + plot_y1) / 2:.0f}) rotate(-90)" text-anchor="middle" class="label">{html.escape(y_label)}</text>')
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("</g>")
return "\n".join(parts)
def svg_page(width: int, height: int, body: str) -> str:
return f'''<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" viewBox="0 0 {width} {height}">
<style>
.title {{ font: 700 18px sans-serif; fill: #111; }}
.label {{ font: 13px sans-serif; fill: #222; }}
.tick {{ font: 11px sans-serif; fill: #555; }}
.legend {{ font: 12px monospace; fill: #222; }}
.axis {{ stroke: #333; stroke-width: 1.2; }}
.grid {{ stroke: #ddd; stroke-width: 0.8; }}
.plot-bg {{ fill: #fff; stroke: #bbb; stroke-width: 1; }}
</style>
<rect width="100%" height="100%" fill="#fff" />
{body}
</svg>
'''
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'<g transform="translate(0,{i * chart_h})">{sub}</g>')
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())
+304
View File
@@ -0,0 +1,304 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="2520" viewBox="0 0 1100 2520">
<style>
.title { font: 700 18px sans-serif; fill: #111; }
.label { font: 13px sans-serif; fill: #222; }
.tick { font: 11px sans-serif; fill: #555; }
.legend { font: 12px monospace; fill: #222; }
.axis { stroke: #333; stroke-width: 1.2; }
.grid { stroke: #ddd; stroke-width: 0.8; }
.plot-bg { fill: #fff; stroke: #bbb; stroke-width: 1; }
</style>
<rect width="100%" height="100%" fill="#fff" />
<g transform="translate(0,0)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random bytes: 10-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="275.98" x2="950" y2="275.98" class="grid" />
<text x="64" y="279.98" text-anchor="end" class="tick">0.1</text>
<line x1="72" y1="189.96" x2="950" y2="189.96" class="grid" />
<text x="64" y="193.96" text-anchor="end" class="tick">0.2</text>
<line x1="72" y1="103.94" x2="950" y2="103.94" class="grid" />
<text x="64" y="107.94" text-anchor="end" class="tick">0.3</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,42.00 218.33,43.72 364.67,49.74 511.00,47.16 657.33,47.16 803.67,53.18 950.00,47.16" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#1f77b4" /><circle cx="218.33" cy="43.72" r="3" fill="#1f77b4" /><circle cx="364.67" cy="49.74" r="3" fill="#1f77b4" /><circle cx="511.00" cy="47.16" r="3" fill="#1f77b4" /><circle cx="657.33" cy="47.16" r="3" fill="#1f77b4" /><circle cx="803.67" cy="53.18" r="3" fill="#1f77b4" /><circle cx="950.00" cy="47.16" r="3" fill="#1f77b4" />
<polyline points="72.00,51.46 218.33,53.18 364.67,48.02 511.00,50.60 657.33,61.78 803.67,48.88 950.00,52.32" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="51.46" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="53.18" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="48.02" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="50.60" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="61.78" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="48.88" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="52.32" r="3" fill="#ff7f0e" />
<polyline points="72.00,47.16 218.33,56.62 364.67,58.34 511.00,48.88 657.33,43.72 803.67,48.88 950.00,46.30" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="47.16" r="3" fill="#2ca02c" /><circle cx="218.33" cy="56.62" r="3" fill="#2ca02c" /><circle cx="364.67" cy="58.34" r="3" fill="#2ca02c" /><circle cx="511.00" cy="48.88" r="3" fill="#2ca02c" /><circle cx="657.33" cy="43.72" r="3" fill="#2ca02c" /><circle cx="803.67" cy="48.88" r="3" fill="#2ca02c" /><circle cx="950.00" cy="46.30" r="3" fill="#2ca02c" />
<polyline points="72.00,54.04 218.33,49.74 364.67,60.06 511.00,52.32 657.33,57.48 803.67,55.76 950.00,54.04" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="54.04" r="3" fill="#d62728" /><circle cx="218.33" cy="49.74" r="3" fill="#d62728" /><circle cx="364.67" cy="60.06" r="3" fill="#d62728" /><circle cx="511.00" cy="52.32" r="3" fill="#d62728" /><circle cx="657.33" cy="57.48" r="3" fill="#d62728" /><circle cx="803.67" cy="55.76" r="3" fill="#d62728" /><circle cx="950.00" cy="54.04" r="3" fill="#d62728" />
<polyline points="72.00,44.58 218.33,53.18 364.67,50.60 511.00,48.88 657.33,59.20 803.67,51.46 950.00,60.92" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="44.58" r="3" fill="#9467bd" /><circle cx="218.33" cy="53.18" r="3" fill="#9467bd" /><circle cx="364.67" cy="50.60" r="3" fill="#9467bd" /><circle cx="511.00" cy="48.88" r="3" fill="#9467bd" /><circle cx="657.33" cy="59.20" r="3" fill="#9467bd" /><circle cx="803.67" cy="51.46" r="3" fill="#9467bd" /><circle cx="950.00" cy="60.92" r="3" fill="#9467bd" />
<polyline points="72.00,51.46 218.33,48.88 364.67,48.88 511.00,48.02 657.33,52.32 803.67,49.74 950.00,55.76" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="51.46" r="3" fill="#8c564b" /><circle cx="218.33" cy="48.88" r="3" fill="#8c564b" /><circle cx="364.67" cy="48.88" r="3" fill="#8c564b" /><circle cx="511.00" cy="48.02" r="3" fill="#8c564b" /><circle cx="657.33" cy="52.32" r="3" fill="#8c564b" /><circle cx="803.67" cy="49.74" r="3" fill="#8c564b" /><circle cx="950.00" cy="55.76" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,420)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random bytes: 12-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="310.39" x2="950" y2="310.39" class="grid" />
<text x="64" y="314.39" text-anchor="end" class="tick">0.02</text>
<line x1="72" y1="258.77" x2="950" y2="258.77" class="grid" />
<text x="64" y="262.77" text-anchor="end" class="tick">0.04</text>
<line x1="72" y1="207.16" x2="950" y2="207.16" class="grid" />
<text x="64" y="211.16" text-anchor="end" class="tick">0.06</text>
<line x1="72" y1="155.55" x2="950" y2="155.55" class="grid" />
<text x="64" y="159.55" text-anchor="end" class="tick">0.08</text>
<line x1="72" y1="103.94" x2="950" y2="103.94" class="grid" />
<text x="64" y="107.94" text-anchor="end" class="tick">0.1</text>
<line x1="72" y1="52.32" x2="950" y2="52.32" class="grid" />
<text x="64" y="56.32" text-anchor="end" class="tick">0.12</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,49.74 218.33,88.45 364.67,80.71 511.00,62.65 657.33,54.90 803.67,72.97 950.00,72.97" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="49.74" r="3" fill="#1f77b4" /><circle cx="218.33" cy="88.45" r="3" fill="#1f77b4" /><circle cx="364.67" cy="80.71" r="3" fill="#1f77b4" /><circle cx="511.00" cy="62.65" r="3" fill="#1f77b4" /><circle cx="657.33" cy="54.90" r="3" fill="#1f77b4" /><circle cx="803.67" cy="72.97" r="3" fill="#1f77b4" /><circle cx="950.00" cy="72.97" r="3" fill="#1f77b4" />
<polyline points="72.00,72.97 218.33,80.71 364.67,70.39 511.00,57.48 657.33,75.55 803.67,54.90 950.00,91.03" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="72.97" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="80.71" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="70.39" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="57.48" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="75.55" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="54.90" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="91.03" r="3" fill="#ff7f0e" />
<polyline points="72.00,49.74 218.33,78.13 364.67,85.87 511.00,83.29 657.33,67.81 803.67,72.97 950.00,57.48" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="49.74" r="3" fill="#2ca02c" /><circle cx="218.33" cy="78.13" r="3" fill="#2ca02c" /><circle cx="364.67" cy="85.87" r="3" fill="#2ca02c" /><circle cx="511.00" cy="83.29" r="3" fill="#2ca02c" /><circle cx="657.33" cy="67.81" r="3" fill="#2ca02c" /><circle cx="803.67" cy="72.97" r="3" fill="#2ca02c" /><circle cx="950.00" cy="57.48" r="3" fill="#2ca02c" />
<polyline points="72.00,78.13 218.33,67.81 364.67,83.29 511.00,72.97 657.33,72.97 803.67,83.29 950.00,96.19" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="78.13" r="3" fill="#d62728" /><circle cx="218.33" cy="67.81" r="3" fill="#d62728" /><circle cx="364.67" cy="83.29" r="3" fill="#d62728" /><circle cx="511.00" cy="72.97" r="3" fill="#d62728" /><circle cx="657.33" cy="72.97" r="3" fill="#d62728" /><circle cx="803.67" cy="83.29" r="3" fill="#d62728" /><circle cx="950.00" cy="96.19" r="3" fill="#d62728" />
<polyline points="72.00,75.55 218.33,54.90 364.67,103.94 511.00,70.39 657.33,75.55 803.67,52.32 950.00,103.94" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="75.55" r="3" fill="#9467bd" /><circle cx="218.33" cy="54.90" r="3" fill="#9467bd" /><circle cx="364.67" cy="103.94" r="3" fill="#9467bd" /><circle cx="511.00" cy="70.39" r="3" fill="#9467bd" /><circle cx="657.33" cy="75.55" r="3" fill="#9467bd" /><circle cx="803.67" cy="52.32" r="3" fill="#9467bd" /><circle cx="950.00" cy="103.94" r="3" fill="#9467bd" />
<polyline points="72.00,80.71 218.33,42.00 364.67,60.06 511.00,78.13 657.33,85.87 803.67,67.81 950.00,52.32" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="80.71" r="3" fill="#8c564b" /><circle cx="218.33" cy="42.00" r="3" fill="#8c564b" /><circle cx="364.67" cy="60.06" r="3" fill="#8c564b" /><circle cx="511.00" cy="78.13" r="3" fill="#8c564b" /><circle cx="657.33" cy="85.87" r="3" fill="#8c564b" /><circle cx="803.67" cy="67.81" r="3" fill="#8c564b" /><circle cx="950.00" cy="52.32" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,840)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random bytes: 16-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="308.67" x2="950" y2="308.67" class="grid" />
<text x="64" y="312.67" text-anchor="end" class="tick">2.00e-03</text>
<line x1="72" y1="255.33" x2="950" y2="255.33" class="grid" />
<text x="64" y="259.33" text-anchor="end" class="tick">4.00e-03</text>
<line x1="72" y1="202.00" x2="950" y2="202.00" class="grid" />
<text x="64" y="206.00" text-anchor="end" class="tick">6.00e-03</text>
<line x1="72" y1="148.67" x2="950" y2="148.67" class="grid" />
<text x="64" y="152.67" text-anchor="end" class="tick">8.00e-03</text>
<line x1="72" y1="95.33" x2="950" y2="95.33" class="grid" />
<text x="64" y="99.33" text-anchor="end" class="tick">0.01</text>
<line x1="72" y1="42.00" x2="950" y2="42.00" class="grid" />
<text x="64" y="46.00" text-anchor="end" class="tick">0.012</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,148.67 218.33,202.00 364.67,202.00 511.00,175.33 657.33,95.33 803.67,202.00 950.00,255.33" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="148.67" r="3" fill="#1f77b4" /><circle cx="218.33" cy="202.00" r="3" fill="#1f77b4" /><circle cx="364.67" cy="202.00" r="3" fill="#1f77b4" /><circle cx="511.00" cy="175.33" r="3" fill="#1f77b4" /><circle cx="657.33" cy="95.33" r="3" fill="#1f77b4" /><circle cx="803.67" cy="202.00" r="3" fill="#1f77b4" /><circle cx="950.00" cy="255.33" r="3" fill="#1f77b4" />
<polyline points="72.00,122.00 218.33,95.33 364.67,175.33 511.00,95.33 657.33,148.67 803.67,122.00 950.00,175.33" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="122.00" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="95.33" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="175.33" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="95.33" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="148.67" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="122.00" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="175.33" r="3" fill="#ff7f0e" />
<polyline points="72.00,175.33 218.33,175.33 364.67,148.67 511.00,148.67 657.33,202.00 803.67,175.33 950.00,122.00" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="175.33" r="3" fill="#2ca02c" /><circle cx="218.33" cy="175.33" r="3" fill="#2ca02c" /><circle cx="364.67" cy="148.67" r="3" fill="#2ca02c" /><circle cx="511.00" cy="148.67" r="3" fill="#2ca02c" /><circle cx="657.33" cy="202.00" r="3" fill="#2ca02c" /><circle cx="803.67" cy="175.33" r="3" fill="#2ca02c" /><circle cx="950.00" cy="122.00" r="3" fill="#2ca02c" />
<polyline points="72.00,202.00 218.33,148.67 364.67,202.00 511.00,122.00 657.33,255.33 803.67,175.33 950.00,202.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#d62728" /><circle cx="218.33" cy="148.67" r="3" fill="#d62728" /><circle cx="364.67" cy="202.00" r="3" fill="#d62728" /><circle cx="511.00" cy="122.00" r="3" fill="#d62728" /><circle cx="657.33" cy="255.33" r="3" fill="#d62728" /><circle cx="803.67" cy="175.33" r="3" fill="#d62728" /><circle cx="950.00" cy="202.00" r="3" fill="#d62728" />
<polyline points="72.00,95.33 218.33,148.67 364.67,202.00 511.00,148.67 657.33,42.00 803.67,148.67 950.00,228.67" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="95.33" r="3" fill="#9467bd" /><circle cx="218.33" cy="148.67" r="3" fill="#9467bd" /><circle cx="364.67" cy="202.00" r="3" fill="#9467bd" /><circle cx="511.00" cy="148.67" r="3" fill="#9467bd" /><circle cx="657.33" cy="42.00" r="3" fill="#9467bd" /><circle cx="803.67" cy="148.67" r="3" fill="#9467bd" /><circle cx="950.00" cy="228.67" r="3" fill="#9467bd" />
<polyline points="72.00,148.67 218.33,148.67 364.67,122.00 511.00,175.33 657.33,175.33 803.67,255.33 950.00,175.33" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="148.67" r="3" fill="#8c564b" /><circle cx="218.33" cy="148.67" r="3" fill="#8c564b" /><circle cx="364.67" cy="122.00" r="3" fill="#8c564b" /><circle cx="511.00" cy="175.33" r="3" fill="#8c564b" /><circle cx="657.33" cy="175.33" r="3" fill="#8c564b" /><circle cx="803.67" cy="255.33" r="3" fill="#8c564b" /><circle cx="950.00" cy="175.33" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,1260)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random bytes: 20-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="298.00" x2="950" y2="298.00" class="grid" />
<text x="64" y="302.00" text-anchor="end" class="tick">2.00e-04</text>
<line x1="72" y1="234.00" x2="950" y2="234.00" class="grid" />
<text x="64" y="238.00" text-anchor="end" class="tick">4.00e-04</text>
<line x1="72" y1="170.00" x2="950" y2="170.00" class="grid" />
<text x="64" y="174.00" text-anchor="end" class="tick">6.00e-04</text>
<line x1="72" y1="106.00" x2="950" y2="106.00" class="grid" />
<text x="64" y="110.00" text-anchor="end" class="tick">8.00e-04</text>
<line x1="72" y1="42.00" x2="950" y2="42.00" class="grid" />
<text x="64" y="46.00" text-anchor="end" class="tick">1.00e-03</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,362.00 218.33,42.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,42.00 950.00,362.00" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#1f77b4" /><circle cx="218.33" cy="42.00" r="3" fill="#1f77b4" /><circle cx="364.67" cy="362.00" r="3" fill="#1f77b4" /><circle cx="511.00" cy="362.00" r="3" fill="#1f77b4" /><circle cx="657.33" cy="362.00" r="3" fill="#1f77b4" /><circle cx="803.67" cy="42.00" r="3" fill="#1f77b4" /><circle cx="950.00" cy="362.00" r="3" fill="#1f77b4" />
<polyline points="72.00,42.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,42.00" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="42.00" r="3" fill="#ff7f0e" />
<polyline points="72.00,362.00 218.33,362.00 364.67,362.00 511.00,42.00 657.33,362.00 803.67,362.00 950.00,42.00" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#2ca02c" /><circle cx="218.33" cy="362.00" r="3" fill="#2ca02c" /><circle cx="364.67" cy="362.00" r="3" fill="#2ca02c" /><circle cx="511.00" cy="42.00" r="3" fill="#2ca02c" /><circle cx="657.33" cy="362.00" r="3" fill="#2ca02c" /><circle cx="803.67" cy="362.00" r="3" fill="#2ca02c" /><circle cx="950.00" cy="42.00" r="3" fill="#2ca02c" />
<polyline points="72.00,362.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,42.00 803.67,362.00 950.00,362.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#d62728" /><circle cx="218.33" cy="362.00" r="3" fill="#d62728" /><circle cx="364.67" cy="362.00" r="3" fill="#d62728" /><circle cx="511.00" cy="362.00" r="3" fill="#d62728" /><circle cx="657.33" cy="42.00" r="3" fill="#d62728" /><circle cx="803.67" cy="362.00" r="3" fill="#d62728" /><circle cx="950.00" cy="362.00" r="3" fill="#d62728" />
<polyline points="72.00,42.00 218.33,362.00 364.67,42.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,362.00" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#9467bd" /><circle cx="218.33" cy="362.00" r="3" fill="#9467bd" /><circle cx="364.67" cy="42.00" r="3" fill="#9467bd" /><circle cx="511.00" cy="362.00" r="3" fill="#9467bd" /><circle cx="657.33" cy="362.00" r="3" fill="#9467bd" /><circle cx="803.67" cy="362.00" r="3" fill="#9467bd" /><circle cx="950.00" cy="362.00" r="3" fill="#9467bd" />
<polyline points="72.00,362.00 218.33,362.00 364.67,42.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,42.00" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#8c564b" /><circle cx="218.33" cy="362.00" r="3" fill="#8c564b" /><circle cx="364.67" cy="42.00" r="3" fill="#8c564b" /><circle cx="511.00" cy="362.00" r="3" fill="#8c564b" /><circle cx="657.33" cy="362.00" r="3" fill="#8c564b" /><circle cx="803.67" cy="362.00" r="3" fill="#8c564b" /><circle cx="950.00" cy="42.00" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,1680)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random bytes: 24-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="202.00" x2="950" y2="202.00" class="grid" />
<text x="64" y="206.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#1f77b4" /><circle cx="218.33" cy="202.00" r="3" fill="#1f77b4" /><circle cx="364.67" cy="202.00" r="3" fill="#1f77b4" /><circle cx="511.00" cy="202.00" r="3" fill="#1f77b4" /><circle cx="657.33" cy="202.00" r="3" fill="#1f77b4" /><circle cx="803.67" cy="202.00" r="3" fill="#1f77b4" /><circle cx="950.00" cy="202.00" r="3" fill="#1f77b4" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="202.00" r="3" fill="#ff7f0e" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#2ca02c" /><circle cx="218.33" cy="202.00" r="3" fill="#2ca02c" /><circle cx="364.67" cy="202.00" r="3" fill="#2ca02c" /><circle cx="511.00" cy="202.00" r="3" fill="#2ca02c" /><circle cx="657.33" cy="202.00" r="3" fill="#2ca02c" /><circle cx="803.67" cy="202.00" r="3" fill="#2ca02c" /><circle cx="950.00" cy="202.00" r="3" fill="#2ca02c" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#d62728" /><circle cx="218.33" cy="202.00" r="3" fill="#d62728" /><circle cx="364.67" cy="202.00" r="3" fill="#d62728" /><circle cx="511.00" cy="202.00" r="3" fill="#d62728" /><circle cx="657.33" cy="202.00" r="3" fill="#d62728" /><circle cx="803.67" cy="202.00" r="3" fill="#d62728" /><circle cx="950.00" cy="202.00" r="3" fill="#d62728" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#9467bd" /><circle cx="218.33" cy="202.00" r="3" fill="#9467bd" /><circle cx="364.67" cy="202.00" r="3" fill="#9467bd" /><circle cx="511.00" cy="202.00" r="3" fill="#9467bd" /><circle cx="657.33" cy="202.00" r="3" fill="#9467bd" /><circle cx="803.67" cy="202.00" r="3" fill="#9467bd" /><circle cx="950.00" cy="202.00" r="3" fill="#9467bd" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#8c564b" /><circle cx="218.33" cy="202.00" r="3" fill="#8c564b" /><circle cx="364.67" cy="202.00" r="3" fill="#8c564b" /><circle cx="511.00" cy="202.00" r="3" fill="#8c564b" /><circle cx="657.33" cy="202.00" r="3" fill="#8c564b" /><circle cx="803.67" cy="202.00" r="3" fill="#8c564b" /><circle cx="950.00" cy="202.00" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,2100)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random bytes: 32-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="202.00" x2="950" y2="202.00" class="grid" />
<text x="64" y="206.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#1f77b4" /><circle cx="218.33" cy="202.00" r="3" fill="#1f77b4" /><circle cx="364.67" cy="202.00" r="3" fill="#1f77b4" /><circle cx="511.00" cy="202.00" r="3" fill="#1f77b4" /><circle cx="657.33" cy="202.00" r="3" fill="#1f77b4" /><circle cx="803.67" cy="202.00" r="3" fill="#1f77b4" /><circle cx="950.00" cy="202.00" r="3" fill="#1f77b4" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="202.00" r="3" fill="#ff7f0e" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#2ca02c" /><circle cx="218.33" cy="202.00" r="3" fill="#2ca02c" /><circle cx="364.67" cy="202.00" r="3" fill="#2ca02c" /><circle cx="511.00" cy="202.00" r="3" fill="#2ca02c" /><circle cx="657.33" cy="202.00" r="3" fill="#2ca02c" /><circle cx="803.67" cy="202.00" r="3" fill="#2ca02c" /><circle cx="950.00" cy="202.00" r="3" fill="#2ca02c" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#d62728" /><circle cx="218.33" cy="202.00" r="3" fill="#d62728" /><circle cx="364.67" cy="202.00" r="3" fill="#d62728" /><circle cx="511.00" cy="202.00" r="3" fill="#d62728" /><circle cx="657.33" cy="202.00" r="3" fill="#d62728" /><circle cx="803.67" cy="202.00" r="3" fill="#d62728" /><circle cx="950.00" cy="202.00" r="3" fill="#d62728" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#9467bd" /><circle cx="218.33" cy="202.00" r="3" fill="#9467bd" /><circle cx="364.67" cy="202.00" r="3" fill="#9467bd" /><circle cx="511.00" cy="202.00" r="3" fill="#9467bd" /><circle cx="657.33" cy="202.00" r="3" fill="#9467bd" /><circle cx="803.67" cy="202.00" r="3" fill="#9467bd" /><circle cx="950.00" cy="202.00" r="3" fill="#9467bd" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#8c564b" /><circle cx="218.33" cy="202.00" r="3" fill="#8c564b" /><circle cx="364.67" cy="202.00" r="3" fill="#8c564b" /><circle cx="511.00" cy="202.00" r="3" fill="#8c564b" /><circle cx="657.33" cy="202.00" r="3" fill="#8c564b" /><circle cx="803.67" cy="202.00" r="3" fill="#8c564b" /><circle cx="950.00" cy="202.00" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
</svg>

After

Width:  |  Height:  |  Size: 37 KiB

+312
View File
@@ -0,0 +1,312 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="2520" viewBox="0 0 1100 2520">
<style>
.title { font: 700 18px sans-serif; fill: #111; }
.label { font: 13px sans-serif; fill: #222; }
.tick { font: 11px sans-serif; fill: #555; }
.legend { font: 12px monospace; fill: #222; }
.axis { stroke: #333; stroke-width: 1.2; }
.grid { stroke: #ddd; stroke-width: 0.8; }
.plot-bg { fill: #fff; stroke: #bbb; stroke-width: 1; }
</style>
<rect width="100%" height="100%" fill="#fff" />
<g transform="translate(0,0)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random a-zA-Z strings: 10-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="275.75" x2="950" y2="275.75" class="grid" />
<text x="64" y="279.75" text-anchor="end" class="tick">0.1</text>
<line x1="72" y1="189.49" x2="950" y2="189.49" class="grid" />
<text x="64" y="193.49" text-anchor="end" class="tick">0.2</text>
<line x1="72" y1="103.24" x2="950" y2="103.24" class="grid" />
<text x="64" y="107.24" text-anchor="end" class="tick">0.3</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,60.98 218.33,52.35 364.67,54.94 511.00,48.04 657.33,55.80 803.67,52.35 950.00,51.49" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="60.98" r="3" fill="#1f77b4" /><circle cx="218.33" cy="52.35" r="3" fill="#1f77b4" /><circle cx="364.67" cy="54.94" r="3" fill="#1f77b4" /><circle cx="511.00" cy="48.04" r="3" fill="#1f77b4" /><circle cx="657.33" cy="55.80" r="3" fill="#1f77b4" /><circle cx="803.67" cy="52.35" r="3" fill="#1f77b4" /><circle cx="950.00" cy="51.49" r="3" fill="#1f77b4" />
<polyline points="72.00,54.94 218.33,54.94 364.67,48.04 511.00,45.45 657.33,46.31 803.67,54.94 950.00,48.90" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="54.94" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="54.94" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="48.04" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="45.45" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="46.31" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="54.94" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="48.90" r="3" fill="#ff7f0e" />
<polyline points="72.00,52.35 218.33,57.53 364.67,57.53 511.00,58.39 657.33,65.29 803.67,50.63 950.00,56.66" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="52.35" r="3" fill="#2ca02c" /><circle cx="218.33" cy="57.53" r="3" fill="#2ca02c" /><circle cx="364.67" cy="57.53" r="3" fill="#2ca02c" /><circle cx="511.00" cy="58.39" r="3" fill="#2ca02c" /><circle cx="657.33" cy="65.29" r="3" fill="#2ca02c" /><circle cx="803.67" cy="50.63" r="3" fill="#2ca02c" /><circle cx="950.00" cy="56.66" r="3" fill="#2ca02c" />
<polyline points="72.00,51.49 218.33,49.76 364.67,52.35 511.00,48.04 657.33,50.63 803.67,47.18 950.00,45.45" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="51.49" r="3" fill="#d62728" /><circle cx="218.33" cy="49.76" r="3" fill="#d62728" /><circle cx="364.67" cy="52.35" r="3" fill="#d62728" /><circle cx="511.00" cy="48.04" r="3" fill="#d62728" /><circle cx="657.33" cy="50.63" r="3" fill="#d62728" /><circle cx="803.67" cy="47.18" r="3" fill="#d62728" /><circle cx="950.00" cy="45.45" r="3" fill="#d62728" />
<polyline points="72.00,42.00 218.33,46.31 364.67,57.53 511.00,60.98 657.33,59.25 803.67,61.84 950.00,51.49" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#9467bd" /><circle cx="218.33" cy="46.31" r="3" fill="#9467bd" /><circle cx="364.67" cy="57.53" r="3" fill="#9467bd" /><circle cx="511.00" cy="60.98" r="3" fill="#9467bd" /><circle cx="657.33" cy="59.25" r="3" fill="#9467bd" /><circle cx="803.67" cy="61.84" r="3" fill="#9467bd" /><circle cx="950.00" cy="51.49" r="3" fill="#9467bd" />
<polyline points="72.00,42.00 218.33,52.35 364.67,43.73 511.00,51.49 657.33,45.45 803.67,50.63 950.00,47.18" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#8c564b" /><circle cx="218.33" cy="52.35" r="3" fill="#8c564b" /><circle cx="364.67" cy="43.73" r="3" fill="#8c564b" /><circle cx="511.00" cy="51.49" r="3" fill="#8c564b" /><circle cx="657.33" cy="45.45" r="3" fill="#8c564b" /><circle cx="803.67" cy="50.63" r="3" fill="#8c564b" /><circle cx="950.00" cy="47.18" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,420)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random a-zA-Z strings: 12-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="310.80" x2="950" y2="310.80" class="grid" />
<text x="64" y="314.80" text-anchor="end" class="tick">0.02</text>
<line x1="72" y1="259.60" x2="950" y2="259.60" class="grid" />
<text x="64" y="263.60" text-anchor="end" class="tick">0.04</text>
<line x1="72" y1="208.40" x2="950" y2="208.40" class="grid" />
<text x="64" y="212.40" text-anchor="end" class="tick">0.06</text>
<line x1="72" y1="157.20" x2="950" y2="157.20" class="grid" />
<text x="64" y="161.20" text-anchor="end" class="tick">0.08</text>
<line x1="72" y1="106.00" x2="950" y2="106.00" class="grid" />
<text x="64" y="110.00" text-anchor="end" class="tick">0.1</text>
<line x1="72" y1="54.80" x2="950" y2="54.80" class="grid" />
<text x="64" y="58.80" text-anchor="end" class="tick">0.12</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,88.08 218.33,85.52 364.67,57.36 511.00,93.20 657.33,75.28 803.67,72.72 950.00,62.48" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="88.08" r="3" fill="#1f77b4" /><circle cx="218.33" cy="85.52" r="3" fill="#1f77b4" /><circle cx="364.67" cy="57.36" r="3" fill="#1f77b4" /><circle cx="511.00" cy="93.20" r="3" fill="#1f77b4" /><circle cx="657.33" cy="75.28" r="3" fill="#1f77b4" /><circle cx="803.67" cy="72.72" r="3" fill="#1f77b4" /><circle cx="950.00" cy="62.48" r="3" fill="#1f77b4" />
<polyline points="72.00,67.60 218.33,106.00 364.67,67.60 511.00,85.52 657.33,72.72 803.67,90.64 950.00,65.04" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="67.60" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="106.00" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="67.60" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="85.52" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="72.72" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="90.64" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="65.04" r="3" fill="#ff7f0e" />
<polyline points="72.00,82.96 218.33,88.08 364.67,88.08 511.00,82.96 657.33,98.32 803.67,67.60 950.00,65.04" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="82.96" r="3" fill="#2ca02c" /><circle cx="218.33" cy="88.08" r="3" fill="#2ca02c" /><circle cx="364.67" cy="88.08" r="3" fill="#2ca02c" /><circle cx="511.00" cy="82.96" r="3" fill="#2ca02c" /><circle cx="657.33" cy="98.32" r="3" fill="#2ca02c" /><circle cx="803.67" cy="67.60" r="3" fill="#2ca02c" /><circle cx="950.00" cy="65.04" r="3" fill="#2ca02c" />
<polyline points="72.00,95.76 218.33,70.16 364.67,70.16 511.00,57.36 657.33,72.72 803.67,93.20 950.00,42.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="95.76" r="3" fill="#d62728" /><circle cx="218.33" cy="70.16" r="3" fill="#d62728" /><circle cx="364.67" cy="70.16" r="3" fill="#d62728" /><circle cx="511.00" cy="57.36" r="3" fill="#d62728" /><circle cx="657.33" cy="72.72" r="3" fill="#d62728" /><circle cx="803.67" cy="93.20" r="3" fill="#d62728" /><circle cx="950.00" cy="42.00" r="3" fill="#d62728" />
<polyline points="72.00,72.72 218.33,65.04 364.67,65.04 511.00,65.04 657.33,88.08 803.67,90.64 950.00,70.16" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="72.72" r="3" fill="#9467bd" /><circle cx="218.33" cy="65.04" r="3" fill="#9467bd" /><circle cx="364.67" cy="65.04" r="3" fill="#9467bd" /><circle cx="511.00" cy="65.04" r="3" fill="#9467bd" /><circle cx="657.33" cy="88.08" r="3" fill="#9467bd" /><circle cx="803.67" cy="90.64" r="3" fill="#9467bd" /><circle cx="950.00" cy="70.16" r="3" fill="#9467bd" />
<polyline points="72.00,67.60 218.33,59.92 364.67,70.16 511.00,72.72 657.33,72.72 803.67,77.84 950.00,44.56" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="67.60" r="3" fill="#8c564b" /><circle cx="218.33" cy="59.92" r="3" fill="#8c564b" /><circle cx="364.67" cy="70.16" r="3" fill="#8c564b" /><circle cx="511.00" cy="72.72" r="3" fill="#8c564b" /><circle cx="657.33" cy="72.72" r="3" fill="#8c564b" /><circle cx="803.67" cy="77.84" r="3" fill="#8c564b" /><circle cx="950.00" cy="44.56" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,840)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random a-zA-Z strings: 16-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="298.00" x2="950" y2="298.00" class="grid" />
<text x="64" y="302.00" text-anchor="end" class="tick">2.00e-03</text>
<line x1="72" y1="234.00" x2="950" y2="234.00" class="grid" />
<text x="64" y="238.00" text-anchor="end" class="tick">4.00e-03</text>
<line x1="72" y1="170.00" x2="950" y2="170.00" class="grid" />
<text x="64" y="174.00" text-anchor="end" class="tick">6.00e-03</text>
<line x1="72" y1="106.00" x2="950" y2="106.00" class="grid" />
<text x="64" y="110.00" text-anchor="end" class="tick">8.00e-03</text>
<line x1="72" y1="42.00" x2="950" y2="42.00" class="grid" />
<text x="64" y="46.00" text-anchor="end" class="tick">0.01</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,74.00 218.33,74.00 364.67,106.00 511.00,42.00 657.33,106.00 803.67,170.00 950.00,170.00" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="74.00" r="3" fill="#1f77b4" /><circle cx="218.33" cy="74.00" r="3" fill="#1f77b4" /><circle cx="364.67" cy="106.00" r="3" fill="#1f77b4" /><circle cx="511.00" cy="42.00" r="3" fill="#1f77b4" /><circle cx="657.33" cy="106.00" r="3" fill="#1f77b4" /><circle cx="803.67" cy="170.00" r="3" fill="#1f77b4" /><circle cx="950.00" cy="170.00" r="3" fill="#1f77b4" />
<polyline points="72.00,74.00 218.33,74.00 364.67,74.00 511.00,202.00 657.33,74.00 803.67,202.00 950.00,106.00" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="74.00" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="74.00" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="74.00" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="74.00" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="106.00" r="3" fill="#ff7f0e" />
<polyline points="72.00,42.00 218.33,170.00 364.67,138.00 511.00,42.00 657.33,170.00 803.67,138.00 950.00,234.00" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#2ca02c" /><circle cx="218.33" cy="170.00" r="3" fill="#2ca02c" /><circle cx="364.67" cy="138.00" r="3" fill="#2ca02c" /><circle cx="511.00" cy="42.00" r="3" fill="#2ca02c" /><circle cx="657.33" cy="170.00" r="3" fill="#2ca02c" /><circle cx="803.67" cy="138.00" r="3" fill="#2ca02c" /><circle cx="950.00" cy="234.00" r="3" fill="#2ca02c" />
<polyline points="72.00,106.00 218.33,170.00 364.67,202.00 511.00,106.00 657.33,74.00 803.67,170.00 950.00,42.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="106.00" r="3" fill="#d62728" /><circle cx="218.33" cy="170.00" r="3" fill="#d62728" /><circle cx="364.67" cy="202.00" r="3" fill="#d62728" /><circle cx="511.00" cy="106.00" r="3" fill="#d62728" /><circle cx="657.33" cy="74.00" r="3" fill="#d62728" /><circle cx="803.67" cy="170.00" r="3" fill="#d62728" /><circle cx="950.00" cy="42.00" r="3" fill="#d62728" />
<polyline points="72.00,74.00 218.33,74.00 364.67,202.00 511.00,202.00 657.33,138.00 803.67,138.00 950.00,170.00" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="74.00" r="3" fill="#9467bd" /><circle cx="218.33" cy="74.00" r="3" fill="#9467bd" /><circle cx="364.67" cy="202.00" r="3" fill="#9467bd" /><circle cx="511.00" cy="202.00" r="3" fill="#9467bd" /><circle cx="657.33" cy="138.00" r="3" fill="#9467bd" /><circle cx="803.67" cy="138.00" r="3" fill="#9467bd" /><circle cx="950.00" cy="170.00" r="3" fill="#9467bd" />
<polyline points="72.00,170.00 218.33,202.00 364.67,74.00 511.00,138.00 657.33,74.00 803.67,170.00 950.00,106.00" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="170.00" r="3" fill="#8c564b" /><circle cx="218.33" cy="202.00" r="3" fill="#8c564b" /><circle cx="364.67" cy="74.00" r="3" fill="#8c564b" /><circle cx="511.00" cy="138.00" r="3" fill="#8c564b" /><circle cx="657.33" cy="74.00" r="3" fill="#8c564b" /><circle cx="803.67" cy="170.00" r="3" fill="#8c564b" /><circle cx="950.00" cy="106.00" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,1260)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random a-zA-Z strings: 20-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="298.00" x2="950" y2="298.00" class="grid" />
<text x="64" y="302.00" text-anchor="end" class="tick">2.00e-04</text>
<line x1="72" y1="234.00" x2="950" y2="234.00" class="grid" />
<text x="64" y="238.00" text-anchor="end" class="tick">4.00e-04</text>
<line x1="72" y1="170.00" x2="950" y2="170.00" class="grid" />
<text x="64" y="174.00" text-anchor="end" class="tick">6.00e-04</text>
<line x1="72" y1="106.00" x2="950" y2="106.00" class="grid" />
<text x="64" y="110.00" text-anchor="end" class="tick">8.00e-04</text>
<line x1="72" y1="42.00" x2="950" y2="42.00" class="grid" />
<text x="64" y="46.00" text-anchor="end" class="tick">1.00e-03</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,42.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,42.00 803.67,362.00 950.00,362.00" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#1f77b4" /><circle cx="218.33" cy="362.00" r="3" fill="#1f77b4" /><circle cx="364.67" cy="362.00" r="3" fill="#1f77b4" /><circle cx="511.00" cy="362.00" r="3" fill="#1f77b4" /><circle cx="657.33" cy="42.00" r="3" fill="#1f77b4" /><circle cx="803.67" cy="362.00" r="3" fill="#1f77b4" /><circle cx="950.00" cy="362.00" r="3" fill="#1f77b4" />
<polyline points="72.00,42.00 218.33,42.00 364.67,362.00 511.00,362.00 657.33,42.00 803.67,362.00 950.00,362.00" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="42.00" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="42.00" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="362.00" r="3" fill="#ff7f0e" />
<polyline points="72.00,42.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,42.00 803.67,42.00 950.00,362.00" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#2ca02c" /><circle cx="218.33" cy="362.00" r="3" fill="#2ca02c" /><circle cx="364.67" cy="362.00" r="3" fill="#2ca02c" /><circle cx="511.00" cy="362.00" r="3" fill="#2ca02c" /><circle cx="657.33" cy="42.00" r="3" fill="#2ca02c" /><circle cx="803.67" cy="42.00" r="3" fill="#2ca02c" /><circle cx="950.00" cy="362.00" r="3" fill="#2ca02c" />
<polyline points="72.00,362.00 218.33,42.00 364.67,362.00 511.00,42.00 657.33,362.00 803.67,362.00 950.00,362.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#d62728" /><circle cx="218.33" cy="42.00" r="3" fill="#d62728" /><circle cx="364.67" cy="362.00" r="3" fill="#d62728" /><circle cx="511.00" cy="42.00" r="3" fill="#d62728" /><circle cx="657.33" cy="362.00" r="3" fill="#d62728" /><circle cx="803.67" cy="362.00" r="3" fill="#d62728" /><circle cx="950.00" cy="362.00" r="3" fill="#d62728" />
<polyline points="72.00,362.00 218.33,42.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,42.00 950.00,362.00" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#9467bd" /><circle cx="218.33" cy="42.00" r="3" fill="#9467bd" /><circle cx="364.67" cy="362.00" r="3" fill="#9467bd" /><circle cx="511.00" cy="362.00" r="3" fill="#9467bd" /><circle cx="657.33" cy="362.00" r="3" fill="#9467bd" /><circle cx="803.67" cy="42.00" r="3" fill="#9467bd" /><circle cx="950.00" cy="362.00" r="3" fill="#9467bd" />
<polyline points="72.00,42.00 218.33,362.00 364.67,42.00 511.00,362.00 657.33,42.00 803.67,362.00 950.00,362.00" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#8c564b" /><circle cx="218.33" cy="362.00" r="3" fill="#8c564b" /><circle cx="364.67" cy="42.00" r="3" fill="#8c564b" /><circle cx="511.00" cy="362.00" r="3" fill="#8c564b" /><circle cx="657.33" cy="42.00" r="3" fill="#8c564b" /><circle cx="803.67" cy="362.00" r="3" fill="#8c564b" /><circle cx="950.00" cy="362.00" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,1680)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random a-zA-Z strings: 24-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="362.00" x2="950" y2="362.00" class="grid" />
<text x="64" y="366.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="298.00" x2="950" y2="298.00" class="grid" />
<text x="64" y="302.00" text-anchor="end" class="tick">2.00e-04</text>
<line x1="72" y1="234.00" x2="950" y2="234.00" class="grid" />
<text x="64" y="238.00" text-anchor="end" class="tick">4.00e-04</text>
<line x1="72" y1="170.00" x2="950" y2="170.00" class="grid" />
<text x="64" y="174.00" text-anchor="end" class="tick">6.00e-04</text>
<line x1="72" y1="106.00" x2="950" y2="106.00" class="grid" />
<text x="64" y="110.00" text-anchor="end" class="tick">8.00e-04</text>
<line x1="72" y1="42.00" x2="950" y2="42.00" class="grid" />
<text x="64" y="46.00" text-anchor="end" class="tick">1.00e-03</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,362.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,362.00" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#1f77b4" /><circle cx="218.33" cy="362.00" r="3" fill="#1f77b4" /><circle cx="364.67" cy="362.00" r="3" fill="#1f77b4" /><circle cx="511.00" cy="362.00" r="3" fill="#1f77b4" /><circle cx="657.33" cy="362.00" r="3" fill="#1f77b4" /><circle cx="803.67" cy="362.00" r="3" fill="#1f77b4" /><circle cx="950.00" cy="362.00" r="3" fill="#1f77b4" />
<polyline points="72.00,362.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,362.00" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="362.00" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="362.00" r="3" fill="#ff7f0e" />
<polyline points="72.00,362.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,362.00" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#2ca02c" /><circle cx="218.33" cy="362.00" r="3" fill="#2ca02c" /><circle cx="364.67" cy="362.00" r="3" fill="#2ca02c" /><circle cx="511.00" cy="362.00" r="3" fill="#2ca02c" /><circle cx="657.33" cy="362.00" r="3" fill="#2ca02c" /><circle cx="803.67" cy="362.00" r="3" fill="#2ca02c" /><circle cx="950.00" cy="362.00" r="3" fill="#2ca02c" />
<polyline points="72.00,362.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,362.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#d62728" /><circle cx="218.33" cy="362.00" r="3" fill="#d62728" /><circle cx="364.67" cy="362.00" r="3" fill="#d62728" /><circle cx="511.00" cy="362.00" r="3" fill="#d62728" /><circle cx="657.33" cy="362.00" r="3" fill="#d62728" /><circle cx="803.67" cy="362.00" r="3" fill="#d62728" /><circle cx="950.00" cy="362.00" r="3" fill="#d62728" />
<polyline points="72.00,362.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,362.00" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="362.00" r="3" fill="#9467bd" /><circle cx="218.33" cy="362.00" r="3" fill="#9467bd" /><circle cx="364.67" cy="362.00" r="3" fill="#9467bd" /><circle cx="511.00" cy="362.00" r="3" fill="#9467bd" /><circle cx="657.33" cy="362.00" r="3" fill="#9467bd" /><circle cx="803.67" cy="362.00" r="3" fill="#9467bd" /><circle cx="950.00" cy="362.00" r="3" fill="#9467bd" />
<polyline points="72.00,42.00 218.33,362.00 364.67,362.00 511.00,362.00 657.33,362.00 803.67,362.00 950.00,362.00" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="42.00" r="3" fill="#8c564b" /><circle cx="218.33" cy="362.00" r="3" fill="#8c564b" /><circle cx="364.67" cy="362.00" r="3" fill="#8c564b" /><circle cx="511.00" cy="362.00" r="3" fill="#8c564b" /><circle cx="657.33" cy="362.00" r="3" fill="#8c564b" /><circle cx="803.67" cy="362.00" r="3" fill="#8c564b" /><circle cx="950.00" cy="362.00" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
<g transform="translate(0,2100)"><g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Random a-zA-Z strings: 32-bit truncated hash collision rate</text>
<rect x="72" y="42" width="878" height="320" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="362" class="grid" />
<text x="72.00" y="380" text-anchor="middle" class="tick">4</text>
<line x1="218.33" y1="42" x2="218.33" y2="362" class="grid" />
<text x="218.33" y="380" text-anchor="middle" class="tick">8</text>
<line x1="364.67" y1="42" x2="364.67" y2="362" class="grid" />
<text x="364.67" y="380" text-anchor="middle" class="tick">16</text>
<line x1="511.00" y1="42" x2="511.00" y2="362" class="grid" />
<text x="511.00" y="380" text-anchor="middle" class="tick">32</text>
<line x1="657.33" y1="42" x2="657.33" y2="362" class="grid" />
<text x="657.33" y="380" text-anchor="middle" class="tick">64</text>
<line x1="803.67" y1="42" x2="803.67" y2="362" class="grid" />
<text x="803.67" y="380" text-anchor="middle" class="tick">128</text>
<line x1="950.00" y1="42" x2="950.00" y2="362" class="grid" />
<text x="950.00" y="380" text-anchor="middle" class="tick">256</text>
<line x1="72" y1="202.00" x2="950" y2="202.00" class="grid" />
<text x="64" y="206.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="362" x2="950" y2="362" class="axis" />
<line x1="72" y1="42" x2="72" y2="362" class="axis" />
<text x="511" y="406" text-anchor="middle" class="label">input length, bytes/chars (log scale)</text>
<text transform="translate(18,202) rotate(-90)" text-anchor="middle" class="label">median collision rate</text>
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#1f77b4" /><circle cx="218.33" cy="202.00" r="3" fill="#1f77b4" /><circle cx="364.67" cy="202.00" r="3" fill="#1f77b4" /><circle cx="511.00" cy="202.00" r="3" fill="#1f77b4" /><circle cx="657.33" cy="202.00" r="3" fill="#1f77b4" /><circle cx="803.67" cy="202.00" r="3" fill="#1f77b4" /><circle cx="950.00" cy="202.00" r="3" fill="#1f77b4" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="218.33" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="364.67" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="657.33" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="803.67" cy="202.00" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="202.00" r="3" fill="#ff7f0e" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#2ca02c" /><circle cx="218.33" cy="202.00" r="3" fill="#2ca02c" /><circle cx="364.67" cy="202.00" r="3" fill="#2ca02c" /><circle cx="511.00" cy="202.00" r="3" fill="#2ca02c" /><circle cx="657.33" cy="202.00" r="3" fill="#2ca02c" /><circle cx="803.67" cy="202.00" r="3" fill="#2ca02c" /><circle cx="950.00" cy="202.00" r="3" fill="#2ca02c" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#d62728" /><circle cx="218.33" cy="202.00" r="3" fill="#d62728" /><circle cx="364.67" cy="202.00" r="3" fill="#d62728" /><circle cx="511.00" cy="202.00" r="3" fill="#d62728" /><circle cx="657.33" cy="202.00" r="3" fill="#d62728" /><circle cx="803.67" cy="202.00" r="3" fill="#d62728" /><circle cx="950.00" cy="202.00" r="3" fill="#d62728" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#9467bd" /><circle cx="218.33" cy="202.00" r="3" fill="#9467bd" /><circle cx="364.67" cy="202.00" r="3" fill="#9467bd" /><circle cx="511.00" cy="202.00" r="3" fill="#9467bd" /><circle cx="657.33" cy="202.00" r="3" fill="#9467bd" /><circle cx="803.67" cy="202.00" r="3" fill="#9467bd" /><circle cx="950.00" cy="202.00" r="3" fill="#9467bd" />
<polyline points="72.00,202.00 218.33,202.00 364.67,202.00 511.00,202.00 657.33,202.00 803.67,202.00 950.00,202.00" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="202.00" r="3" fill="#8c564b" /><circle cx="218.33" cy="202.00" r="3" fill="#8c564b" /><circle cx="364.67" cy="202.00" r="3" fill="#8c564b" /><circle cx="511.00" cy="202.00" r="3" fill="#8c564b" /><circle cx="657.33" cy="202.00" r="3" fill="#8c564b" /><circle cx="803.67" cy="202.00" r="3" fill="#8c564b" /><circle cx="950.00" cy="202.00" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g></g>
</svg>

After

Width:  |  Height:  |  Size: 38 KiB

+72
View File
@@ -0,0 +1,72 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1100" height="620" viewBox="0 0 1100 620">
<style>
.title { font: 700 18px sans-serif; fill: #111; }
.label { font: 13px sans-serif; fill: #222; }
.tick { font: 11px sans-serif; fill: #555; }
.legend { font: 12px monospace; fill: #222; }
.axis { stroke: #333; stroke-width: 1.2; }
.grid { stroke: #ddd; stroke-width: 0.8; }
.plot-bg { fill: #fff; stroke: #bbb; stroke-width: 1; }
</style>
<rect width="100%" height="100%" fill="#fff" />
<g class="chart">
<text x="550" y="22" text-anchor="middle" class="title">Hash speed on random bytes (median GiB/s)</text>
<rect x="72" y="42" width="878" height="520" class="plot-bg" />
<line x1="72.00" y1="42" x2="72.00" y2="562" class="grid" />
<text x="72.00" y="580" text-anchor="middle" class="tick">1</text>
<line x1="159.80" y1="42" x2="159.80" y2="562" class="grid" />
<text x="159.80" y="580" text-anchor="middle" class="tick">4</text>
<line x1="203.70" y1="42" x2="203.70" y2="562" class="grid" />
<text x="203.70" y="580" text-anchor="middle" class="tick">8</text>
<line x1="247.60" y1="42" x2="247.60" y2="562" class="grid" />
<text x="247.60" y="580" text-anchor="middle" class="tick">16</text>
<line x1="291.50" y1="42" x2="291.50" y2="562" class="grid" />
<text x="291.50" y="580" text-anchor="middle" class="tick">32</text>
<line x1="335.40" y1="42" x2="335.40" y2="562" class="grid" />
<text x="335.40" y="580" text-anchor="middle" class="tick">64</text>
<line x1="379.30" y1="42" x2="379.30" y2="562" class="grid" />
<text x="379.30" y="580" text-anchor="middle" class="tick">128</text>
<line x1="423.20" y1="42" x2="423.20" y2="562" class="grid" />
<text x="423.20" y="580" text-anchor="middle" class="tick">256</text>
<line x1="511.00" y1="42" x2="511.00" y2="562" class="grid" />
<text x="511.00" y="580" text-anchor="middle" class="tick">1024</text>
<line x1="598.80" y1="42" x2="598.80" y2="562" class="grid" />
<text x="598.80" y="580" text-anchor="middle" class="tick">4096</text>
<line x1="686.60" y1="42" x2="686.60" y2="562" class="grid" />
<text x="686.60" y="580" text-anchor="middle" class="tick">1.64e+04</text>
<line x1="774.40" y1="42" x2="774.40" y2="562" class="grid" />
<text x="774.40" y="580" text-anchor="middle" class="tick">6.55e+04</text>
<line x1="950.00" y1="42" x2="950.00" y2="562" class="grid" />
<text x="950.00" y="580" text-anchor="middle" class="tick">1.05e+06</text>
<line x1="72" y1="562.00" x2="950" y2="562.00" class="grid" />
<text x="64" y="566.00" text-anchor="end" class="tick">0</text>
<line x1="72" y1="396.83" x2="950" y2="396.83" class="grid" />
<text x="64" y="400.83" text-anchor="end" class="tick">5</text>
<line x1="72" y1="231.65" x2="950" y2="231.65" class="grid" />
<text x="64" y="235.65" text-anchor="end" class="tick">10</text>
<line x1="72" y1="66.48" x2="950" y2="66.48" class="grid" />
<text x="64" y="70.48" text-anchor="end" class="tick">15</text>
<line x1="72" y1="562" x2="950" y2="562" class="axis" />
<line x1="72" y1="42" x2="72" y2="562" class="axis" />
<text x="511" y="606" text-anchor="middle" class="label">input length, bytes (log scale)</text>
<text transform="translate(18,302) rotate(-90)" text-anchor="middle" class="label">median GiB/s</text>
<polyline points="72.00,555.66 159.80,537.55 203.70,516.71 247.60,498.82 291.50,476.85 335.40,437.57 379.30,435.32 423.20,409.49 511.00,391.00 598.80,387.21 686.60,388.12 774.40,429.67 950.00,412.95" fill="none" stroke="#1f77b4" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="555.66" r="3" fill="#1f77b4" /><circle cx="159.80" cy="537.55" r="3" fill="#1f77b4" /><circle cx="203.70" cy="516.71" r="3" fill="#1f77b4" /><circle cx="247.60" cy="498.82" r="3" fill="#1f77b4" /><circle cx="291.50" cy="476.85" r="3" fill="#1f77b4" /><circle cx="335.40" cy="437.57" r="3" fill="#1f77b4" /><circle cx="379.30" cy="435.32" r="3" fill="#1f77b4" /><circle cx="423.20" cy="409.49" r="3" fill="#1f77b4" /><circle cx="511.00" cy="391.00" r="3" fill="#1f77b4" /><circle cx="598.80" cy="387.21" r="3" fill="#1f77b4" /><circle cx="686.60" cy="388.12" r="3" fill="#1f77b4" /><circle cx="774.40" cy="429.67" r="3" fill="#1f77b4" /><circle cx="950.00" cy="412.95" r="3" fill="#1f77b4" />
<polyline points="72.00,558.28 159.80,548.97 203.70,523.86 247.60,496.69 291.50,491.97 335.40,448.11 379.30,388.26 423.20,359.36 511.00,280.00 598.80,260.11 686.60,308.90 774.40,257.71 950.00,261.83" fill="none" stroke="#ff7f0e" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="558.28" r="3" fill="#ff7f0e" /><circle cx="159.80" cy="548.97" r="3" fill="#ff7f0e" /><circle cx="203.70" cy="523.86" r="3" fill="#ff7f0e" /><circle cx="247.60" cy="496.69" r="3" fill="#ff7f0e" /><circle cx="291.50" cy="491.97" r="3" fill="#ff7f0e" /><circle cx="335.40" cy="448.11" r="3" fill="#ff7f0e" /><circle cx="379.30" cy="388.26" r="3" fill="#ff7f0e" /><circle cx="423.20" cy="359.36" r="3" fill="#ff7f0e" /><circle cx="511.00" cy="280.00" r="3" fill="#ff7f0e" /><circle cx="598.80" cy="260.11" r="3" fill="#ff7f0e" /><circle cx="686.60" cy="308.90" r="3" fill="#ff7f0e" /><circle cx="774.40" cy="257.71" r="3" fill="#ff7f0e" /><circle cx="950.00" cy="261.83" r="3" fill="#ff7f0e" />
<polyline points="72.00,556.47 159.80,530.81 203.70,499.64 247.60,447.64 291.50,424.62 335.40,356.05 379.30,256.66 423.20,285.10 511.00,107.02 598.80,55.59 686.60,42.00 774.40,173.36 950.00,136.75" fill="none" stroke="#2ca02c" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="556.47" r="3" fill="#2ca02c" /><circle cx="159.80" cy="530.81" r="3" fill="#2ca02c" /><circle cx="203.70" cy="499.64" r="3" fill="#2ca02c" /><circle cx="247.60" cy="447.64" r="3" fill="#2ca02c" /><circle cx="291.50" cy="424.62" r="3" fill="#2ca02c" /><circle cx="335.40" cy="356.05" r="3" fill="#2ca02c" /><circle cx="379.30" cy="256.66" r="3" fill="#2ca02c" /><circle cx="423.20" cy="285.10" r="3" fill="#2ca02c" /><circle cx="511.00" cy="107.02" r="3" fill="#2ca02c" /><circle cx="598.80" cy="55.59" r="3" fill="#2ca02c" /><circle cx="686.60" cy="42.00" r="3" fill="#2ca02c" /><circle cx="774.40" cy="173.36" r="3" fill="#2ca02c" /><circle cx="950.00" cy="136.75" r="3" fill="#2ca02c" />
<polyline points="72.00,557.33 159.80,547.72 203.70,530.36 247.60,514.68 291.50,503.06 335.40,485.10 379.30,457.87 423.20,436.61 511.00,426.55 598.80,415.88 686.60,416.08 774.40,422.04 950.00,419.91" fill="none" stroke="#d62728" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="557.33" r="3" fill="#d62728" /><circle cx="159.80" cy="547.72" r="3" fill="#d62728" /><circle cx="203.70" cy="530.36" r="3" fill="#d62728" /><circle cx="247.60" cy="514.68" r="3" fill="#d62728" /><circle cx="291.50" cy="503.06" r="3" fill="#d62728" /><circle cx="335.40" cy="485.10" r="3" fill="#d62728" /><circle cx="379.30" cy="457.87" r="3" fill="#d62728" /><circle cx="423.20" cy="436.61" r="3" fill="#d62728" /><circle cx="511.00" cy="426.55" r="3" fill="#d62728" /><circle cx="598.80" cy="415.88" r="3" fill="#d62728" /><circle cx="686.60" cy="416.08" r="3" fill="#d62728" /><circle cx="774.40" cy="422.04" r="3" fill="#d62728" /><circle cx="950.00" cy="419.91" r="3" fill="#d62728" />
<polyline points="72.00,555.41 159.80,530.83 203.70,504.98 247.60,447.76 291.50,340.61 335.40,331.69 379.30,346.88 423.20,287.25 511.00,212.30 598.80,188.65 686.60,191.14 774.40,236.69 950.00,245.34" fill="none" stroke="#9467bd" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="555.41" r="3" fill="#9467bd" /><circle cx="159.80" cy="530.83" r="3" fill="#9467bd" /><circle cx="203.70" cy="504.98" r="3" fill="#9467bd" /><circle cx="247.60" cy="447.76" r="3" fill="#9467bd" /><circle cx="291.50" cy="340.61" r="3" fill="#9467bd" /><circle cx="335.40" cy="331.69" r="3" fill="#9467bd" /><circle cx="379.30" cy="346.88" r="3" fill="#9467bd" /><circle cx="423.20" cy="287.25" r="3" fill="#9467bd" /><circle cx="511.00" cy="212.30" r="3" fill="#9467bd" /><circle cx="598.80" cy="188.65" r="3" fill="#9467bd" /><circle cx="686.60" cy="191.14" r="3" fill="#9467bd" /><circle cx="774.40" cy="236.69" r="3" fill="#9467bd" /><circle cx="950.00" cy="245.34" r="3" fill="#9467bd" />
<polyline points="72.00,554.88 159.80,543.93 203.70,539.24 247.60,539.96 291.50,542.69 335.40,544.56 379.30,544.36 423.20,544.07 511.00,544.46 598.80,544.36 686.60,543.54 774.40,544.09 950.00,544.19" fill="none" stroke="#8c564b" stroke-width="2" stroke-linejoin="round" stroke-linecap="round" /><circle cx="72.00" cy="554.88" r="3" fill="#8c564b" /><circle cx="159.80" cy="543.93" r="3" fill="#8c564b" /><circle cx="203.70" cy="539.24" r="3" fill="#8c564b" /><circle cx="247.60" cy="539.96" r="3" fill="#8c564b" /><circle cx="291.50" cy="542.69" r="3" fill="#8c564b" /><circle cx="335.40" cy="544.56" r="3" fill="#8c564b" /><circle cx="379.30" cy="544.36" r="3" fill="#8c564b" /><circle cx="423.20" cy="544.07" r="3" fill="#8c564b" /><circle cx="511.00" cy="544.46" r="3" fill="#8c564b" /><circle cx="598.80" cy="544.36" r="3" fill="#8c564b" /><circle cx="686.60" cy="543.54" r="3" fill="#8c564b" /><circle cx="774.40" cy="544.09" r="3" fill="#8c564b" /><circle cx="950.00" cy="544.19" r="3" fill="#8c564b" />
<rect x="976" y="48" width="12" height="12" fill="#1f77b4" />
<text x="994" y="58" class="legend">xxh32</text>
<rect x="976" y="66" width="12" height="12" fill="#ff7f0e" />
<text x="994" y="76" class="legend">xxh64</text>
<rect x="976" y="84" width="12" height="12" fill="#2ca02c" />
<text x="994" y="94" class="legend">xxh3_64</text>
<rect x="976" y="102" width="12" height="12" fill="#d62728" />
<text x="994" y="112" class="legend">city32</text>
<rect x="976" y="120" width="12" height="12" fill="#9467bd" />
<text x="994" y="130" class="legend">city64</text>
<rect x="976" y="138" width="12" height="12" fill="#8c564b" />
<text x="994" y="148" class="legend">joaat</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.7 KiB

+192
View File
@@ -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 <algorithm>
#include <chrono>
#include <cstdint>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <random>
#include <string>
#include <string_view>
#include <vector>
#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<const char *>(data), len);
}
static uint64_t hash_city64(const void *data, size_t len)
{
return CityHash64(static_cast<const char *>(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<size_t>(iters, 128);
iters = std::min<size_t>(iters, max_iters);
return iters;
}
static double median(std::vector<double> 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<unsigned char> random_bytes(size_t len)
{
std::vector<unsigned char> data(len);
std::mt19937_64 rng(0x415253565f686173ULL ^ len);
for (unsigned char &byte : data) {
byte = static_cast<unsigned char>(rng() & 0xffu);
}
return data;
}
static uint64_t bench_once(HashFn fn, const std::vector<unsigned char> &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<size_t> lengths = {
1, 4, 8, 16, 32, 64, 128, 256, 1024, 4096, 16384, 65536, 1048576,
};
const std::vector<HashCase> 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<unsigned char> data = random_bytes(len);
const size_t iters = iterations_for(len, target_bytes, max_iters);
std::vector<double> ns_per_hash;
std::vector<double> gib_per_s;
uint64_t sink = 0;
/* Warmup outside measured runs. */
sink ^= bench_once(hash.fn, data, std::min<size_t>(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<double>(stop - start).count();
const double bytes = static_cast<double>(len) * static_cast<double>(iters);
ns_per_hash.push_back(seconds * 1e9 / static_cast<double>(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;
}
+14
View File
@@ -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
+14
View File
@@ -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
+14
View File
@@ -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
+14
View File
@@ -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
+14
View File
@@ -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
+14
View File
@@ -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
Submodule hash_testing/src/cityhash added at f5dc54147f
+46
View File
@@ -0,0 +1,46 @@
#include "hash.h"
#include <stddef.h>
#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);
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef ARSV_JOAAT_HASH_H
#define ARSV_JOAAT_HASH_H
#include <stddef.h>
#include <stdint.h>
#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 */
Submodule hash_testing/src/xxHash added at e573d4d2aa