hashcodecs 0.5.0__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/.gitignore +5 -2
- hashcodecs-0.6.0/BENCHMARK.md +58 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/Cargo.lock +22 -3
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/Cargo.toml +19 -5
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/PKG-INFO +39 -65
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/README.md +37 -63
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/benches/base64.rs +1 -1
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/benches/murmur3.rs +1 -1
- hashcodecs-0.6.0/benches/xxhash.rs +119 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/build.rs +5 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/hatch_build.py +2 -2
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/pyproject.toml +4 -3
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/python/hashcodecs/__init__.py +6 -1
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/python/hashcodecs/_hashcodecs.pyi +4 -0
- hashcodecs-0.6.0/python/hashcodecs/xxhash.py +5 -0
- hashcodecs-0.6.0/src/backend.rs +222 -0
- hashcodecs-0.6.0/src/base64/aarch64/decode.rs +229 -0
- hashcodecs-0.6.0/src/base64/aarch64/encode.rs +113 -0
- hashcodecs-0.6.0/src/base64/aarch64/tests.rs +578 -0
- hashcodecs-0.6.0/src/base64/aarch64.rs +11 -0
- hashcodecs-0.6.0/src/base64/backend.rs +87 -0
- hashcodecs-0.5.0/src/base64.rs → hashcodecs-0.6.0/src/base64/decode.rs +39 -310
- hashcodecs-0.6.0/src/base64/dispatch.rs +320 -0
- hashcodecs-0.6.0/src/base64/encode.rs +209 -0
- hashcodecs-0.5.0/src/base64/x86_avx512.rs → hashcodecs-0.6.0/src/base64/x86/avx512.rs +37 -10
- hashcodecs-0.6.0/src/base64/x86/cache.rs +130 -0
- hashcodecs-0.5.0/src/base64/x86.rs → hashcodecs-0.6.0/src/base64/x86/decode.rs +13 -375
- hashcodecs-0.6.0/src/base64/x86/encode.rs +588 -0
- hashcodecs-0.6.0/src/base64/x86.rs +32 -0
- hashcodecs-0.6.0/src/base64.rs +259 -0
- hashcodecs-0.5.0/src/python/base64.rs → hashcodecs-0.6.0/src/bindings/base64/decode.rs +151 -479
- {hashcodecs-0.5.0/src/python → hashcodecs-0.6.0/src/bindings}/base64/encode.rs +20 -18
- hashcodecs-0.6.0/src/bindings/base64/mod.rs +1086 -0
- {hashcodecs-0.5.0/src/python → hashcodecs-0.6.0/src/bindings}/buffer.rs +57 -18
- hashcodecs-0.6.0/src/bindings/mod.rs +314 -0
- hashcodecs-0.5.0/src/python/murmur3.rs → hashcodecs-0.6.0/src/bindings/murmur3/mod.rs +118 -31
- hashcodecs-0.6.0/src/bindings/xxhash/batch.rs +82 -0
- hashcodecs-0.6.0/src/bindings/xxhash/mod.rs +197 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/src/lib.rs +8 -2
- hashcodecs-0.6.0/src/murmur3/dispatch.rs +51 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/src/murmur3/x86.rs +69 -3
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/src/murmur3.rs +217 -165
- hashcodecs-0.6.0/src/xxhash/aarch64.rs +91 -0
- hashcodecs-0.6.0/src/xxhash/x86/avx2.rs +261 -0
- hashcodecs-0.6.0/src/xxhash/x86/avx512.rs +83 -0
- hashcodecs-0.6.0/src/xxhash/x86/sse.rs +88 -0
- hashcodecs-0.6.0/src/xxhash/x86.rs +50 -0
- hashcodecs-0.6.0/src/xxhash.rs +849 -0
- hashcodecs-0.5.0/BENCHMARK.md +0 -113
- hashcodecs-0.5.0/src/base64/aarch64.rs +0 -927
- hashcodecs-0.5.0/src/base64/dispatch.rs +0 -373
- hashcodecs-0.5.0/src/murmur3/dispatch.rs +0 -47
- hashcodecs-0.5.0/src/python.rs +0 -52
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/LICENSE +0 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/LICENSE-MIT +0 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/benches/support/mod.rs +0 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/python/hashcodecs/base64.py +0 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/python/hashcodecs/base64.pyi +0 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/python/hashcodecs/murmur3.py +0 -0
- {hashcodecs-0.5.0 → hashcodecs-0.6.0}/python/hashcodecs/py.typed +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Benchmark Details
|
|
2
|
+
|
|
3
|
+
Environment: Windows 10 x64 and Intel Core Ultra 7 265K.
|
|
4
|
+
|
|
5
|
+
Conditions: clean builds, one pinned logical CPU, single-threaded execution, and 15 Python samples. The upstream C baseline was compiled explicitly for AVX2, matching the backend selected by hashcodecs on this host. Higher is better.
|
|
6
|
+
|
|
7
|
+
Python hashcodecs measurements use a CPython 3.12 wheel built against the full C
|
|
8
|
+
API. Unchanged reference series are retained from their latest clean run.
|
|
9
|
+
|
|
10
|
+
The charts are generated by `uv run python benchmarks/render_charts.py`. Their exact measurements are available in
|
|
11
|
+
[CSV form](docs/benchmarks/results.csv).
|
|
12
|
+
|
|
13
|
+
## XXH3
|
|
14
|
+
|
|
15
|
+
The Rust comparison calls xxHash 0.8.3 through `xxhash-c-sys`. Python compares with the upstream `xxhash` extension.
|
|
16
|
+
Batch measurements contain 32 equal-size inputs.
|
|
17
|
+
|
|
18
|
+
[](docs/benchmarks/xxh3-rust.svg)
|
|
19
|
+
|
|
20
|
+
[](docs/benchmarks/xxh3-python.svg)
|
|
21
|
+
|
|
22
|
+
## Reusable Python Buffers
|
|
23
|
+
|
|
24
|
+
[](docs/benchmarks/base64-python-reusable.svg)
|
|
25
|
+
|
|
26
|
+
## Python Memoryview Inputs
|
|
27
|
+
|
|
28
|
+
Full immutable memoryviews reuse their underlying bytes for inputs of at least 64 KiB.
|
|
29
|
+
|
|
30
|
+
[](docs/benchmarks/base64-python-memoryview.svg)
|
|
31
|
+
|
|
32
|
+
## Python Base64 Batches
|
|
33
|
+
|
|
34
|
+
The horizontal axis is the batch size and the vertical axis is total input throughput.
|
|
35
|
+
|
|
36
|
+
[](docs/benchmarks/base64-python-batch.svg)
|
|
37
|
+
|
|
38
|
+
## Reusable Python Base64 Batch Buffers
|
|
39
|
+
|
|
40
|
+
These measurements use the `*_batch_into` APIs with one reusable `bytearray` per item.
|
|
41
|
+
|
|
42
|
+
[](docs/benchmarks/base64-python-batch-reusable.svg)
|
|
43
|
+
|
|
44
|
+
## Large Python Base64 Batches
|
|
45
|
+
|
|
46
|
+
Each batch item is 1 MiB. The horizontal axis is the batch size.
|
|
47
|
+
|
|
48
|
+
[](docs/benchmarks/base64-python-batch-large.svg)
|
|
49
|
+
|
|
50
|
+
## Mutable Python Inputs
|
|
51
|
+
|
|
52
|
+
### Base64
|
|
53
|
+
|
|
54
|
+
[](docs/benchmarks/base64-python-mutable.svg)
|
|
55
|
+
|
|
56
|
+
### MurmurHash3
|
|
57
|
+
|
|
58
|
+
[](docs/benchmarks/murmur3-python-mutable.svg)
|
|
@@ -46,9 +46,9 @@ checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
|
|
|
46
46
|
|
|
47
47
|
[[package]]
|
|
48
48
|
name = "base64-turbo"
|
|
49
|
-
version = "0.
|
|
49
|
+
version = "0.3.0"
|
|
50
50
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
-
checksum = "
|
|
51
|
+
checksum = "8bb14240b770d247c8481cab7c78350daf08b4285885b916632dec270b7e6dfc"
|
|
52
52
|
|
|
53
53
|
[[package]]
|
|
54
54
|
name = "cast"
|
|
@@ -194,7 +194,7 @@ dependencies = [
|
|
|
194
194
|
|
|
195
195
|
[[package]]
|
|
196
196
|
name = "hashcodecs"
|
|
197
|
-
version = "0.
|
|
197
|
+
version = "0.6.0"
|
|
198
198
|
dependencies = [
|
|
199
199
|
"base64",
|
|
200
200
|
"base64-turbo",
|
|
@@ -206,6 +206,9 @@ dependencies = [
|
|
|
206
206
|
"murmur3",
|
|
207
207
|
"murmurs",
|
|
208
208
|
"pyo3",
|
|
209
|
+
"pyo3-build-config",
|
|
210
|
+
"xxhash-c-sys",
|
|
211
|
+
"xxhash-rust",
|
|
209
212
|
]
|
|
210
213
|
|
|
211
214
|
[[package]]
|
|
@@ -576,6 +579,22 @@ dependencies = [
|
|
|
576
579
|
"windows-link",
|
|
577
580
|
]
|
|
578
581
|
|
|
582
|
+
[[package]]
|
|
583
|
+
name = "xxhash-c-sys"
|
|
584
|
+
version = "0.8.7"
|
|
585
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
586
|
+
checksum = "4d4a8210e2c9209f553817636cc6054d3b22424cc879c31b616e4cb4027be705"
|
|
587
|
+
dependencies = [
|
|
588
|
+
"cc",
|
|
589
|
+
"libc",
|
|
590
|
+
]
|
|
591
|
+
|
|
592
|
+
[[package]]
|
|
593
|
+
name = "xxhash-rust"
|
|
594
|
+
version = "0.8.18"
|
|
595
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
596
|
+
checksum = "aee1b19627c7c60102ab80d3a9cbe18de90bfe03bfa6c3715447681f0e8c8af6"
|
|
597
|
+
|
|
579
598
|
[[package]]
|
|
580
599
|
name = "zerocopy"
|
|
581
600
|
version = "0.8.56"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "hashcodecs"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.6.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
rust-version = "1.89"
|
|
6
|
-
description = "SIMD-accelerated Base64 codecs and fast MurmurHash3 implementations"
|
|
6
|
+
description = "SIMD-accelerated Base64 codecs and fast MurmurHash3 and xxHash implementations"
|
|
7
7
|
license = "MIT OR Apache-2.0"
|
|
8
8
|
repository = "https://github.com/kozistr/hashcodecs-rs"
|
|
9
9
|
publish = false
|
|
10
|
-
keywords = ["base64", "simd", "murmur3", "python"]
|
|
10
|
+
keywords = ["base64", "simd", "murmur3", "xxhash", "python"]
|
|
11
11
|
categories = ["encoding", "algorithms"]
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
|
|
@@ -22,16 +22,21 @@ extension-module = ["python", "pyo3/extension-module"]
|
|
|
22
22
|
[dependencies]
|
|
23
23
|
memchr = { version = "2.8.0", optional = true }
|
|
24
24
|
mimalloc = "0.1.52"
|
|
25
|
-
pyo3 = { version = "0.29.2",
|
|
25
|
+
pyo3 = { version = "0.29.2", optional = true }
|
|
26
|
+
|
|
27
|
+
[build-dependencies]
|
|
28
|
+
pyo3-build-config = "0.29.2"
|
|
26
29
|
|
|
27
30
|
[dev-dependencies]
|
|
28
31
|
base64 = "0.23.1"
|
|
29
|
-
base64-turbo = "0.
|
|
32
|
+
base64-turbo = "0.3.0"
|
|
30
33
|
criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] }
|
|
31
34
|
fastmurmur3 = "0.2.0"
|
|
32
35
|
mm3h = "0.1.3"
|
|
33
36
|
murmur3 = "0.5"
|
|
34
37
|
murmurs = "1.0.5"
|
|
38
|
+
xxhash-c-sys = "0.8.7"
|
|
39
|
+
xxhash-rust = { version = "0.8.18", features = ["xxh3"] }
|
|
35
40
|
|
|
36
41
|
[[bench]]
|
|
37
42
|
name = "base64"
|
|
@@ -41,6 +46,15 @@ harness = false
|
|
|
41
46
|
name = "murmur3"
|
|
42
47
|
harness = false
|
|
43
48
|
|
|
49
|
+
[[bench]]
|
|
50
|
+
name = "xxhash"
|
|
51
|
+
harness = false
|
|
52
|
+
|
|
53
|
+
[[test]]
|
|
54
|
+
name = "sanitizers"
|
|
55
|
+
path = "tests/sanitizers.rs"
|
|
56
|
+
harness = false
|
|
57
|
+
|
|
44
58
|
[profile.release]
|
|
45
59
|
codegen-units = 1
|
|
46
60
|
lto = "fat"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hashcodecs
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: SIMD-accelerated Base64 and
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: SIMD-accelerated Base64, MurmurHash3, and xxHash codecs
|
|
5
5
|
License-Expression: MIT OR Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
License-File: LICENSE-MIT
|
|
@@ -27,14 +27,16 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
[](https://github.com/kozistr/hashcodecs-rs#license)
|
|
28
28
|
[](https://pypi.org/project/hashcodecs/)
|
|
29
29
|
|
|
30
|
-
`hashcodecs` provides runtime-dispatched SIMD Base64 codecs and fast, reference-compatible MurmurHash3 functions for Rust and Python.
|
|
30
|
+
`hashcodecs` provides runtime-dispatched SIMD Base64 codecs and fast, reference-compatible MurmurHash3 and XXH3 functions for Rust and Python.
|
|
31
31
|
|
|
32
32
|
## Design
|
|
33
33
|
|
|
34
34
|
- Runtime-dispatched SIMD Base64 with portable scalar fallbacks.
|
|
35
35
|
- Reference-compatible MurmurHash3 with SIMD acceleration.
|
|
36
|
+
- Bit-for-bit compatible XXH3-64 and XXH3-128 with runtime SIMD dispatch and native batch APIs.
|
|
36
37
|
- Rust and Python `*_into` APIs for caller-managed output buffers.
|
|
37
38
|
- A familiar Python Base64 API, including native batch encode and decode operations.
|
|
39
|
+
- Unsafe paths verified with Kani, strict-provenance Miri, ASan/MSan, and differential fuzzing.
|
|
38
40
|
|
|
39
41
|
## Install
|
|
40
42
|
|
|
@@ -54,13 +56,14 @@ let mut output = [0_u8; 8];
|
|
|
54
56
|
let written = hashcodecs::b64encode_into(b"hello", &mut output).unwrap();
|
|
55
57
|
assert_eq!(&output[..written], b"aGVsbG8=");
|
|
56
58
|
assert_eq!(hashcodecs::murmur3_x86_32(b"hello", 0), 0x248b_fa47);
|
|
59
|
+
assert_eq!(hashcodecs::xxh3_64(b"", 0), 0x2d06_8005_38d3_94c2);
|
|
57
60
|
```
|
|
58
61
|
|
|
59
62
|
### Python
|
|
60
63
|
|
|
61
64
|
```python
|
|
62
65
|
import hashcodecs.base64 as base64
|
|
63
|
-
from hashcodecs import murmur3_32, murmur3_x64_128
|
|
66
|
+
from hashcodecs import murmur3_32, murmur3_x64_128, xxh3_64, xxh3_128_batch
|
|
64
67
|
|
|
65
68
|
assert base64.b64encode(b'hello') == b'aGVsbG8='
|
|
66
69
|
assert base64.b64decode(b'aGVsbG8=') == b'hello'
|
|
@@ -69,6 +72,11 @@ assert base64.b64decode_batch([b'aGVsbG8=', 'd29ybGQ=']) == [b'hello', b'world']
|
|
|
69
72
|
assert base64.b64encode(b'hello', padded=False) == b'aGVsbG8'
|
|
70
73
|
assert base64.b64decode(b'aGVsbG8', padded=False, canonical=True) == b'hello'
|
|
71
74
|
assert murmur3_32(b'hello') == 0x248BFA47
|
|
75
|
+
assert xxh3_64(b'') == 0x2D06800538D394C2
|
|
76
|
+
assert xxh3_128_batch([b'hello', b'world']) == [
|
|
77
|
+
0xB5E9C1AD071B3E7FC779CFAA5E523818,
|
|
78
|
+
0xFA0D38A9B38280D0891E4985BDB2583E,
|
|
79
|
+
]
|
|
72
80
|
|
|
73
81
|
payload = b'hello'
|
|
74
82
|
encoded = bytearray(4 * ((len(payload) + 2) // 3))
|
|
@@ -102,6 +110,7 @@ Comparison crates are development-only dependencies and are not included in cons
|
|
|
102
110
|
```sh
|
|
103
111
|
cargo bench --bench base64
|
|
104
112
|
cargo bench --bench murmur3
|
|
113
|
+
cargo bench --bench xxhash
|
|
105
114
|
uv sync --group benchmark --no-install-project
|
|
106
115
|
uv run --no-project --with . python benchmarks/python_base64.py
|
|
107
116
|
uv run --no-project --with . python benchmarks/python_base64.py --into
|
|
@@ -111,82 +120,47 @@ uv run --no-project --with . python benchmarks/python_base64_batch.py
|
|
|
111
120
|
uv run --no-project --with . python benchmarks/python_base64_batch.py --large
|
|
112
121
|
uv run --no-project --with . python benchmarks/python_murmur3.py
|
|
113
122
|
uv run --no-project --with . python benchmarks/python_murmur3.py --incremental
|
|
123
|
+
uv run --no-project --with . python benchmarks/python_xxhash.py
|
|
114
124
|
```
|
|
115
125
|
|
|
126
|
+
For regression checks that do not need fresh competitor measurements, pass
|
|
127
|
+
`--hashcodecs-only` to any Python benchmark command.
|
|
128
|
+
|
|
129
|
+
For the same-ISA Windows comparison reported below, rebuild the C baseline with
|
|
130
|
+
`$env:CFLAGS='/O2 /arch:AVX2'; cargo clean -p xxhash-c-sys; cargo bench --bench xxhash`.
|
|
131
|
+
|
|
116
132
|
## Base64: Rust
|
|
117
133
|
|
|
118
|
-
|
|
119
|
-
| --- | --- | --- | ---: | ---: | ---: |
|
|
120
|
-
| Standard | 4 KiB | encode | **20.41 GiB/s** | 5.81 GiB/s | 18.29 GiB/s |
|
|
121
|
-
| | 4 KiB | decode | **27.11 GiB/s** | 4.33 GiB/s | 16.95 GiB/s |
|
|
122
|
-
| | 1 MiB | encode | **42.38 GiB/s** | 5.16 GiB/s | 19.60 GiB/s |
|
|
123
|
-
| | 1 MiB | decode | **31.07 GiB/s** | 4.10 GiB/s | 18.17 GiB/s |
|
|
124
|
-
| | 32 MiB | encode | **11.97 GiB/s** | 3.28 GiB/s | 10.94 GiB/s |
|
|
125
|
-
| | 32 MiB | decode | **11.51 GiB/s** | 3.35 GiB/s | 10.45 GiB/s |
|
|
126
|
-
| URL-safe | 4 KiB | encode | **20.46 GiB/s** | 5.81 GiB/s | 18.31 GiB/s |
|
|
127
|
-
| | 4 KiB | decode | **25.65 GiB/s** | 4.35 GiB/s | 16.96 GiB/s |
|
|
128
|
-
| | 1 MiB | encode | **42.56 GiB/s** | 5.18 GiB/s | 19.66 GiB/s |
|
|
129
|
-
| | 1 MiB | decode | **29.42 GiB/s** | 4.08 GiB/s | 18.16 GiB/s |
|
|
130
|
-
| | 32 MiB | encode | **11.86 GiB/s** | 3.29 GiB/s | 11.09 GiB/s |
|
|
131
|
-
| | 32 MiB | decode | **11.67 GiB/s** | 3.36 GiB/s | 10.62 GiB/s |
|
|
134
|
+
[](docs/benchmarks/base64-rust.svg)
|
|
132
135
|
|
|
133
136
|
## MurmurHash3: Rust
|
|
134
137
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
| | 32 MiB | **9.63 GiB/s** | 4.84 GiB/s | 6.05 GiB/s | n/a | n/a |
|
|
143
|
-
| x64 128-bit | 4 KiB | **10.76 GiB/s** | 6.83 GiB/s | 9.45 GiB/s | 10.06 GiB/s | 9.54 GiB/s |
|
|
144
|
-
| | 1 MiB | **10.84 GiB/s** | 6.89 GiB/s | 9.51 GiB/s | 10.04 GiB/s | 9.51 GiB/s |
|
|
145
|
-
| | 32 MiB | **10.12 GiB/s** | 6.11 GiB/s | 6.64 GiB/s | 7.25 GiB/s | 6.70 GiB/s |
|
|
138
|
+
[](docs/benchmarks/murmur3-rust.svg)
|
|
139
|
+
|
|
140
|
+
## XXH3: Rust
|
|
141
|
+
|
|
142
|
+
`upstream C` is xxHash 0.8.3 built through `xxhash-c-sys` with AVX2 enabled, matching the backend selected by hashcodecs on the benchmark host. Batch results hash 32 equal-size inputs and include result-vector allocation.
|
|
143
|
+
|
|
144
|
+
[](docs/benchmarks/xxh3-rust.svg)
|
|
146
145
|
|
|
147
146
|
## Base64: Python
|
|
148
147
|
|
|
149
148
|
Python decoding uses `validate=True`, and `hashcodecs` passes `bytes` directly into Rust without an input copy.
|
|
150
149
|
|
|
151
|
-
|
|
152
|
-
| --- | --- | --- | ---: | ---: | ---: |
|
|
153
|
-
| Standard | 4 KiB | encode | **14.42 GiB/s** | 0.49 GiB/s | 14.36 GiB/s |
|
|
154
|
-
| | 4 KiB | decode | **16.72 GiB/s** | 1.12 GiB/s | 8.35 GiB/s |
|
|
155
|
-
| | 1 MiB | encode | **3.69 GiB/s** | 0.43 GiB/s | 3.51 GiB/s |
|
|
156
|
-
| | 1 MiB | decode | **4.90 GiB/s** | 0.97 GiB/s | 4.60 GiB/s |
|
|
157
|
-
| | 32 MiB | encode | **2.81 GiB/s** | 0.44 GiB/s | 2.60 GiB/s |
|
|
158
|
-
| | 32 MiB | decode | 3.15 GiB/s | 0.93 GiB/s | **3.49 GiB/s** |
|
|
159
|
-
| URL-safe | 4 KiB | encode | **14.48 GiB/s** | 0.40 GiB/s | 1.19 GiB/s |
|
|
160
|
-
| | 4 KiB | decode | **13.45 GiB/s** | 0.75 GiB/s | 1.56 GiB/s |
|
|
161
|
-
| | 1 MiB | encode | **3.96 GiB/s** | 0.36 GiB/s | 0.92 GiB/s |
|
|
162
|
-
| | 1 MiB | decode | **4.53 GiB/s** | 0.61 GiB/s | 1.58 GiB/s |
|
|
163
|
-
| | 32 MiB | encode | **2.64 GiB/s** | 0.34 GiB/s | 0.83 GiB/s |
|
|
164
|
-
| | 32 MiB | decode | **3.15 GiB/s** | 0.60 GiB/s | 1.49 GiB/s |
|
|
150
|
+
[](docs/benchmarks/base64-python.svg)
|
|
165
151
|
|
|
166
152
|
## MurmurHash3: Python
|
|
167
153
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
| | | 32 MiB | **9.12 GiB/s** | 6.15 GiB/s |
|
|
179
|
-
| | incremental | 4 KiB | **7.02 GiB/s** | 0.77 GiB/s |
|
|
180
|
-
| | | 1 MiB | **9.17 GiB/s** | 0.80 GiB/s |
|
|
181
|
-
| | | 32 MiB | **9.01 GiB/s** | 0.79 GiB/s |
|
|
182
|
-
| x64 128-bit | one-shot | 4 KiB | 8.68 GiB/s | **9.46 GiB/s** |
|
|
183
|
-
| | | 1 MiB | 10.10 GiB/s | **10.24 GiB/s** |
|
|
184
|
-
| | | 32 MiB | **9.54 GiB/s** | 6.61 GiB/s |
|
|
185
|
-
| | incremental | 4 KiB | 7.70 GiB/s | **7.99 GiB/s** |
|
|
186
|
-
| | | 1 MiB | **10.01 GiB/s** | 9.28 GiB/s |
|
|
187
|
-
| | | 32 MiB | **9.41 GiB/s** | 7.34 GiB/s |
|
|
188
|
-
|
|
189
|
-
Reusable-buffer and mutable-input results are available in [BENCHMARK.md](https://github.com/kozistr/hashcodecs-rs/blob/main/BENCHMARK.md).
|
|
154
|
+
[](docs/benchmarks/murmur3-python.svg)
|
|
155
|
+
|
|
156
|
+
## XXH3: Python
|
|
157
|
+
|
|
158
|
+
The batch comparison uses one native `hashcodecs` call versus a loop over the upstream `xxhash` extension.
|
|
159
|
+
|
|
160
|
+
[](docs/benchmarks/xxh3-python.svg)
|
|
161
|
+
|
|
162
|
+
Reusable-buffer and mutable-input charts are available in [BENCHMARK.md](BENCHMARK.md). Exact chart values are
|
|
163
|
+
available as [CSV](docs/benchmarks/results.csv).
|
|
190
164
|
|
|
191
165
|
## SIMD References
|
|
192
166
|
|
|
@@ -7,14 +7,16 @@
|
|
|
7
7
|
[](https://github.com/kozistr/hashcodecs-rs#license)
|
|
8
8
|
[](https://pypi.org/project/hashcodecs/)
|
|
9
9
|
|
|
10
|
-
`hashcodecs` provides runtime-dispatched SIMD Base64 codecs and fast, reference-compatible MurmurHash3 functions for Rust and Python.
|
|
10
|
+
`hashcodecs` provides runtime-dispatched SIMD Base64 codecs and fast, reference-compatible MurmurHash3 and XXH3 functions for Rust and Python.
|
|
11
11
|
|
|
12
12
|
## Design
|
|
13
13
|
|
|
14
14
|
- Runtime-dispatched SIMD Base64 with portable scalar fallbacks.
|
|
15
15
|
- Reference-compatible MurmurHash3 with SIMD acceleration.
|
|
16
|
+
- Bit-for-bit compatible XXH3-64 and XXH3-128 with runtime SIMD dispatch and native batch APIs.
|
|
16
17
|
- Rust and Python `*_into` APIs for caller-managed output buffers.
|
|
17
18
|
- A familiar Python Base64 API, including native batch encode and decode operations.
|
|
19
|
+
- Unsafe paths verified with Kani, strict-provenance Miri, ASan/MSan, and differential fuzzing.
|
|
18
20
|
|
|
19
21
|
## Install
|
|
20
22
|
|
|
@@ -34,13 +36,14 @@ let mut output = [0_u8; 8];
|
|
|
34
36
|
let written = hashcodecs::b64encode_into(b"hello", &mut output).unwrap();
|
|
35
37
|
assert_eq!(&output[..written], b"aGVsbG8=");
|
|
36
38
|
assert_eq!(hashcodecs::murmur3_x86_32(b"hello", 0), 0x248b_fa47);
|
|
39
|
+
assert_eq!(hashcodecs::xxh3_64(b"", 0), 0x2d06_8005_38d3_94c2);
|
|
37
40
|
```
|
|
38
41
|
|
|
39
42
|
### Python
|
|
40
43
|
|
|
41
44
|
```python
|
|
42
45
|
import hashcodecs.base64 as base64
|
|
43
|
-
from hashcodecs import murmur3_32, murmur3_x64_128
|
|
46
|
+
from hashcodecs import murmur3_32, murmur3_x64_128, xxh3_64, xxh3_128_batch
|
|
44
47
|
|
|
45
48
|
assert base64.b64encode(b'hello') == b'aGVsbG8='
|
|
46
49
|
assert base64.b64decode(b'aGVsbG8=') == b'hello'
|
|
@@ -49,6 +52,11 @@ assert base64.b64decode_batch([b'aGVsbG8=', 'd29ybGQ=']) == [b'hello', b'world']
|
|
|
49
52
|
assert base64.b64encode(b'hello', padded=False) == b'aGVsbG8'
|
|
50
53
|
assert base64.b64decode(b'aGVsbG8', padded=False, canonical=True) == b'hello'
|
|
51
54
|
assert murmur3_32(b'hello') == 0x248BFA47
|
|
55
|
+
assert xxh3_64(b'') == 0x2D06800538D394C2
|
|
56
|
+
assert xxh3_128_batch([b'hello', b'world']) == [
|
|
57
|
+
0xB5E9C1AD071B3E7FC779CFAA5E523818,
|
|
58
|
+
0xFA0D38A9B38280D0891E4985BDB2583E,
|
|
59
|
+
]
|
|
52
60
|
|
|
53
61
|
payload = b'hello'
|
|
54
62
|
encoded = bytearray(4 * ((len(payload) + 2) // 3))
|
|
@@ -82,6 +90,7 @@ Comparison crates are development-only dependencies and are not included in cons
|
|
|
82
90
|
```sh
|
|
83
91
|
cargo bench --bench base64
|
|
84
92
|
cargo bench --bench murmur3
|
|
93
|
+
cargo bench --bench xxhash
|
|
85
94
|
uv sync --group benchmark --no-install-project
|
|
86
95
|
uv run --no-project --with . python benchmarks/python_base64.py
|
|
87
96
|
uv run --no-project --with . python benchmarks/python_base64.py --into
|
|
@@ -91,82 +100,47 @@ uv run --no-project --with . python benchmarks/python_base64_batch.py
|
|
|
91
100
|
uv run --no-project --with . python benchmarks/python_base64_batch.py --large
|
|
92
101
|
uv run --no-project --with . python benchmarks/python_murmur3.py
|
|
93
102
|
uv run --no-project --with . python benchmarks/python_murmur3.py --incremental
|
|
103
|
+
uv run --no-project --with . python benchmarks/python_xxhash.py
|
|
94
104
|
```
|
|
95
105
|
|
|
106
|
+
For regression checks that do not need fresh competitor measurements, pass
|
|
107
|
+
`--hashcodecs-only` to any Python benchmark command.
|
|
108
|
+
|
|
109
|
+
For the same-ISA Windows comparison reported below, rebuild the C baseline with
|
|
110
|
+
`$env:CFLAGS='/O2 /arch:AVX2'; cargo clean -p xxhash-c-sys; cargo bench --bench xxhash`.
|
|
111
|
+
|
|
96
112
|
## Base64: Rust
|
|
97
113
|
|
|
98
|
-
|
|
99
|
-
| --- | --- | --- | ---: | ---: | ---: |
|
|
100
|
-
| Standard | 4 KiB | encode | **20.41 GiB/s** | 5.81 GiB/s | 18.29 GiB/s |
|
|
101
|
-
| | 4 KiB | decode | **27.11 GiB/s** | 4.33 GiB/s | 16.95 GiB/s |
|
|
102
|
-
| | 1 MiB | encode | **42.38 GiB/s** | 5.16 GiB/s | 19.60 GiB/s |
|
|
103
|
-
| | 1 MiB | decode | **31.07 GiB/s** | 4.10 GiB/s | 18.17 GiB/s |
|
|
104
|
-
| | 32 MiB | encode | **11.97 GiB/s** | 3.28 GiB/s | 10.94 GiB/s |
|
|
105
|
-
| | 32 MiB | decode | **11.51 GiB/s** | 3.35 GiB/s | 10.45 GiB/s |
|
|
106
|
-
| URL-safe | 4 KiB | encode | **20.46 GiB/s** | 5.81 GiB/s | 18.31 GiB/s |
|
|
107
|
-
| | 4 KiB | decode | **25.65 GiB/s** | 4.35 GiB/s | 16.96 GiB/s |
|
|
108
|
-
| | 1 MiB | encode | **42.56 GiB/s** | 5.18 GiB/s | 19.66 GiB/s |
|
|
109
|
-
| | 1 MiB | decode | **29.42 GiB/s** | 4.08 GiB/s | 18.16 GiB/s |
|
|
110
|
-
| | 32 MiB | encode | **11.86 GiB/s** | 3.29 GiB/s | 11.09 GiB/s |
|
|
111
|
-
| | 32 MiB | decode | **11.67 GiB/s** | 3.36 GiB/s | 10.62 GiB/s |
|
|
114
|
+
[](docs/benchmarks/base64-rust.svg)
|
|
112
115
|
|
|
113
116
|
## MurmurHash3: Rust
|
|
114
117
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
| | 32 MiB | **9.63 GiB/s** | 4.84 GiB/s | 6.05 GiB/s | n/a | n/a |
|
|
123
|
-
| x64 128-bit | 4 KiB | **10.76 GiB/s** | 6.83 GiB/s | 9.45 GiB/s | 10.06 GiB/s | 9.54 GiB/s |
|
|
124
|
-
| | 1 MiB | **10.84 GiB/s** | 6.89 GiB/s | 9.51 GiB/s | 10.04 GiB/s | 9.51 GiB/s |
|
|
125
|
-
| | 32 MiB | **10.12 GiB/s** | 6.11 GiB/s | 6.64 GiB/s | 7.25 GiB/s | 6.70 GiB/s |
|
|
118
|
+
[](docs/benchmarks/murmur3-rust.svg)
|
|
119
|
+
|
|
120
|
+
## XXH3: Rust
|
|
121
|
+
|
|
122
|
+
`upstream C` is xxHash 0.8.3 built through `xxhash-c-sys` with AVX2 enabled, matching the backend selected by hashcodecs on the benchmark host. Batch results hash 32 equal-size inputs and include result-vector allocation.
|
|
123
|
+
|
|
124
|
+
[](docs/benchmarks/xxh3-rust.svg)
|
|
126
125
|
|
|
127
126
|
## Base64: Python
|
|
128
127
|
|
|
129
128
|
Python decoding uses `validate=True`, and `hashcodecs` passes `bytes` directly into Rust without an input copy.
|
|
130
129
|
|
|
131
|
-
|
|
132
|
-
| --- | --- | --- | ---: | ---: | ---: |
|
|
133
|
-
| Standard | 4 KiB | encode | **14.42 GiB/s** | 0.49 GiB/s | 14.36 GiB/s |
|
|
134
|
-
| | 4 KiB | decode | **16.72 GiB/s** | 1.12 GiB/s | 8.35 GiB/s |
|
|
135
|
-
| | 1 MiB | encode | **3.69 GiB/s** | 0.43 GiB/s | 3.51 GiB/s |
|
|
136
|
-
| | 1 MiB | decode | **4.90 GiB/s** | 0.97 GiB/s | 4.60 GiB/s |
|
|
137
|
-
| | 32 MiB | encode | **2.81 GiB/s** | 0.44 GiB/s | 2.60 GiB/s |
|
|
138
|
-
| | 32 MiB | decode | 3.15 GiB/s | 0.93 GiB/s | **3.49 GiB/s** |
|
|
139
|
-
| URL-safe | 4 KiB | encode | **14.48 GiB/s** | 0.40 GiB/s | 1.19 GiB/s |
|
|
140
|
-
| | 4 KiB | decode | **13.45 GiB/s** | 0.75 GiB/s | 1.56 GiB/s |
|
|
141
|
-
| | 1 MiB | encode | **3.96 GiB/s** | 0.36 GiB/s | 0.92 GiB/s |
|
|
142
|
-
| | 1 MiB | decode | **4.53 GiB/s** | 0.61 GiB/s | 1.58 GiB/s |
|
|
143
|
-
| | 32 MiB | encode | **2.64 GiB/s** | 0.34 GiB/s | 0.83 GiB/s |
|
|
144
|
-
| | 32 MiB | decode | **3.15 GiB/s** | 0.60 GiB/s | 1.49 GiB/s |
|
|
130
|
+
[](docs/benchmarks/base64-python.svg)
|
|
145
131
|
|
|
146
132
|
## MurmurHash3: Python
|
|
147
133
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
| | | 32 MiB | **9.12 GiB/s** | 6.15 GiB/s |
|
|
159
|
-
| | incremental | 4 KiB | **7.02 GiB/s** | 0.77 GiB/s |
|
|
160
|
-
| | | 1 MiB | **9.17 GiB/s** | 0.80 GiB/s |
|
|
161
|
-
| | | 32 MiB | **9.01 GiB/s** | 0.79 GiB/s |
|
|
162
|
-
| x64 128-bit | one-shot | 4 KiB | 8.68 GiB/s | **9.46 GiB/s** |
|
|
163
|
-
| | | 1 MiB | 10.10 GiB/s | **10.24 GiB/s** |
|
|
164
|
-
| | | 32 MiB | **9.54 GiB/s** | 6.61 GiB/s |
|
|
165
|
-
| | incremental | 4 KiB | 7.70 GiB/s | **7.99 GiB/s** |
|
|
166
|
-
| | | 1 MiB | **10.01 GiB/s** | 9.28 GiB/s |
|
|
167
|
-
| | | 32 MiB | **9.41 GiB/s** | 7.34 GiB/s |
|
|
168
|
-
|
|
169
|
-
Reusable-buffer and mutable-input results are available in [BENCHMARK.md](https://github.com/kozistr/hashcodecs-rs/blob/main/BENCHMARK.md).
|
|
134
|
+
[](docs/benchmarks/murmur3-python.svg)
|
|
135
|
+
|
|
136
|
+
## XXH3: Python
|
|
137
|
+
|
|
138
|
+
The batch comparison uses one native `hashcodecs` call versus a loop over the upstream `xxhash` extension.
|
|
139
|
+
|
|
140
|
+
[](docs/benchmarks/xxh3-python.svg)
|
|
141
|
+
|
|
142
|
+
Reusable-buffer and mutable-input charts are available in [BENCHMARK.md](BENCHMARK.md). Exact chart values are
|
|
143
|
+
available as [CSV](docs/benchmarks/results.csv).
|
|
170
144
|
|
|
171
145
|
## SIMD References
|
|
172
146
|
|
|
@@ -6,7 +6,7 @@ use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_m
|
|
|
6
6
|
|
|
7
7
|
mod support;
|
|
8
8
|
|
|
9
|
-
const SIZES: [usize;
|
|
9
|
+
const SIZES: [usize; 4] = [1024, 4 * 1024, 1024 * 1024, 8 * 1024 * 1024];
|
|
10
10
|
const SAMPLE_SIZE: usize = 50;
|
|
11
11
|
|
|
12
12
|
fn data(size: usize) -> Vec<u8> {
|
|
@@ -6,7 +6,7 @@ use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_m
|
|
|
6
6
|
|
|
7
7
|
mod support;
|
|
8
8
|
|
|
9
|
-
const SIZES: [usize;
|
|
9
|
+
const SIZES: [usize; 4] = [1024, 4 * 1024, 1024 * 1024, 8 * 1024 * 1024];
|
|
10
10
|
const SAMPLE_SIZE: usize = 50;
|
|
11
11
|
|
|
12
12
|
fn data(size: usize) -> Vec<u8> {
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
use std::ffi::c_void;
|
|
2
|
+
use std::hint::black_box;
|
|
3
|
+
use std::time::Duration;
|
|
4
|
+
|
|
5
|
+
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
|
|
6
|
+
|
|
7
|
+
mod support;
|
|
8
|
+
|
|
9
|
+
const SIZES: [usize; 5] = [64, 1024, 4 * 1024, 1024 * 1024, 8 * 1024 * 1024];
|
|
10
|
+
|
|
11
|
+
fn data(size: usize, salt: u8) -> Vec<u8> {
|
|
12
|
+
(0..size)
|
|
13
|
+
.map(|index| (index as u8).wrapping_mul(31).wrapping_add(salt))
|
|
14
|
+
.collect()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
fn c_xxh3_64(input: &[u8], seed: u64) -> u64 {
|
|
18
|
+
unsafe {
|
|
19
|
+
xxhash_c_sys::XXH3_64bits_withSeed(input.as_ptr().cast::<c_void>(), input.len(), seed)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fn c_xxh3_128(input: &[u8], seed: u64) -> [u64; 2] {
|
|
24
|
+
let hash = unsafe {
|
|
25
|
+
xxhash_c_sys::XXH3_128bits_withSeed(input.as_ptr().cast::<c_void>(), input.len(), seed)
|
|
26
|
+
};
|
|
27
|
+
[hash.low64, hash.high64]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
fn one_shot(c: &mut Criterion) {
|
|
31
|
+
for size in SIZES {
|
|
32
|
+
let input = data(size, 17);
|
|
33
|
+
let mut group = c.benchmark_group(format!("xxh3_64/{size}"));
|
|
34
|
+
group.throughput(Throughput::Bytes(size as u64));
|
|
35
|
+
assert_eq!(hashcodecs::xxh3_64(&input, 42), c_xxh3_64(&input, 42));
|
|
36
|
+
group.bench_function("hashcodecs", |bench| {
|
|
37
|
+
bench.iter(|| hashcodecs::xxh3_64(black_box(&input), 42))
|
|
38
|
+
});
|
|
39
|
+
group.bench_function("upstream_c", |bench| {
|
|
40
|
+
bench.iter(|| c_xxh3_64(black_box(&input), 42))
|
|
41
|
+
});
|
|
42
|
+
group.finish();
|
|
43
|
+
|
|
44
|
+
let mut group = c.benchmark_group(format!("xxh3_128/{size}"));
|
|
45
|
+
group.throughput(Throughput::Bytes(size as u64));
|
|
46
|
+
assert_eq!(hashcodecs::xxh3_128(&input, 42), c_xxh3_128(&input, 42));
|
|
47
|
+
group.bench_function("hashcodecs", |bench| {
|
|
48
|
+
bench.iter(|| hashcodecs::xxh3_128(black_box(&input), 42))
|
|
49
|
+
});
|
|
50
|
+
group.bench_function("upstream_c", |bench| {
|
|
51
|
+
bench.iter(|| c_xxh3_128(black_box(&input), 42))
|
|
52
|
+
});
|
|
53
|
+
group.finish();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fn batch(c: &mut Criterion) {
|
|
58
|
+
const ITEMS: usize = 32;
|
|
59
|
+
for size in [64, 1024, 4 * 1024, 1024 * 1024] {
|
|
60
|
+
let owned = (0..ITEMS)
|
|
61
|
+
.map(|index| data(size, index as u8))
|
|
62
|
+
.collect::<Vec<_>>();
|
|
63
|
+
let inputs = owned.iter().map(Vec::as_slice).collect::<Vec<_>>();
|
|
64
|
+
let mut group = c.benchmark_group(format!("xxh3_batch/{size}"));
|
|
65
|
+
group.throughput(Throughput::Bytes((size * ITEMS) as u64));
|
|
66
|
+
|
|
67
|
+
group.bench_with_input(
|
|
68
|
+
BenchmarkId::new("hashcodecs_64", ITEMS),
|
|
69
|
+
&inputs,
|
|
70
|
+
|bench, inputs| bench.iter(|| hashcodecs::xxh3_64_batch(black_box(inputs), 42)),
|
|
71
|
+
);
|
|
72
|
+
group.bench_with_input(
|
|
73
|
+
BenchmarkId::new("upstream_c_64", ITEMS),
|
|
74
|
+
&inputs,
|
|
75
|
+
|bench, inputs| {
|
|
76
|
+
bench.iter(|| {
|
|
77
|
+
inputs
|
|
78
|
+
.iter()
|
|
79
|
+
.map(|input| c_xxh3_64(black_box(input), 42))
|
|
80
|
+
.collect::<Vec<_>>()
|
|
81
|
+
})
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
group.bench_with_input(
|
|
85
|
+
BenchmarkId::new("hashcodecs_128", ITEMS),
|
|
86
|
+
&inputs,
|
|
87
|
+
|bench, inputs| bench.iter(|| hashcodecs::xxh3_128_batch(black_box(inputs), 42)),
|
|
88
|
+
);
|
|
89
|
+
group.bench_with_input(
|
|
90
|
+
BenchmarkId::new("upstream_c_128", ITEMS),
|
|
91
|
+
&inputs,
|
|
92
|
+
|bench, inputs| {
|
|
93
|
+
bench.iter(|| {
|
|
94
|
+
inputs
|
|
95
|
+
.iter()
|
|
96
|
+
.map(|input| c_xxh3_128(black_box(input), 42))
|
|
97
|
+
.collect::<Vec<_>>()
|
|
98
|
+
})
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
group.finish();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fn xxhash(c: &mut Criterion) {
|
|
106
|
+
support::pin_to_one_cpu();
|
|
107
|
+
one_shot(c);
|
|
108
|
+
batch(c);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
criterion_group! {
|
|
112
|
+
name = benches;
|
|
113
|
+
config = Criterion::default()
|
|
114
|
+
.measurement_time(Duration::from_secs(1))
|
|
115
|
+
.sample_size(30)
|
|
116
|
+
.warm_up_time(Duration::from_millis(300));
|
|
117
|
+
targets = xxhash
|
|
118
|
+
}
|
|
119
|
+
criterion_main!(benches);
|