hashcodecs 1.2.1__tar.gz → 1.4.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.
Files changed (189) hide show
  1. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/.gitignore +3 -0
  2. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/BENCHMARK.md +81 -6
  3. hashcodecs-1.4.0/CHANGELOG.md +209 -0
  4. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/CITATION.cff +2 -2
  5. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/Cargo.lock +16 -5
  6. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/Cargo.toml +8 -19
  7. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/PKG-INFO +44 -24
  8. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/README.md +43 -23
  9. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/SAFETY.md +9 -0
  10. hashcodecs-1.4.0/benches/Cargo.toml +37 -0
  11. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/benches/base64.rs +18 -12
  12. hashcodecs-1.4.0/benches/crossover.rs +90 -0
  13. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/benches/murmur3.rs +1 -5
  14. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/benches/support/mod.rs +2 -0
  15. hashcodecs-1.4.0/benches/xxhash.rs +246 -0
  16. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/build.rs +1 -0
  17. hashcodecs-1.4.0/docs/ARCHITECTURE.md +218 -0
  18. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/api/base64.md +2 -2
  19. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/api/murmur3.md +1 -1
  20. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/api/xxh3.md +1 -1
  21. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/performance.md +4 -4
  22. hashcodecs-1.4.0/docs/requirements.txt +2 -0
  23. hashcodecs-1.4.0/generated/rust/binding_schema.rs +1759 -0
  24. hashcodecs-1.4.0/generated/rust/murmur3_classes.rs +34 -0
  25. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/__init__.py +2 -2
  26. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/__init__.pyi +1 -1
  27. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/_hashcodecs.pyi +126 -102
  28. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/base64.py +2 -2
  29. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/base64.pyi +1 -1
  30. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/murmur3.py +2 -2
  31. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/murmur3.pyi +1 -1
  32. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/xxhash.py +2 -2
  33. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/xxhash.pyi +1 -1
  34. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hatch_build.py +58 -6
  35. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/pyproject.toml +21 -9
  36. hashcodecs-1.4.0/src/backend.rs +178 -0
  37. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/alphabet.rs +14 -8
  38. hashcodecs-1.4.0/src/base64/backend.rs +103 -0
  39. hashcodecs-1.4.0/src/base64/decode/aarch64.rs +354 -0
  40. hashcodecs-1.4.0/src/base64/decode/avx2.rs +338 -0
  41. hashcodecs-1.4.0/src/base64/decode/avx512.rs +355 -0
  42. hashcodecs-1.4.0/src/base64/decode/sse41.rs +129 -0
  43. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/decode/ssse3.rs +117 -38
  44. hashcodecs-1.4.0/src/base64/decode/tables.rs +58 -0
  45. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/decode/x86_contracts.rs +37 -4
  46. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/decode.rs +259 -79
  47. hashcodecs-1.4.0/src/base64/encode/aarch64.rs +274 -0
  48. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/encode/avx2.rs +335 -128
  49. hashcodecs-1.4.0/src/base64/encode/avx512.rs +309 -0
  50. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/encode/cache.rs +6 -0
  51. hashcodecs-1.4.0/src/base64/encode/ssse3.rs +165 -0
  52. hashcodecs-1.4.0/src/base64/encode.rs +627 -0
  53. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/miri_tests.rs +2 -0
  54. hashcodecs-1.4.0/src/base64/output_buffer.rs +21 -0
  55. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/proofs.rs +2 -0
  56. hashcodecs-1.4.0/src/base64/runtime_dispatch.rs +918 -0
  57. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/tests/aarch64.rs +45 -7
  58. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/tests.rs +711 -66
  59. hashcodecs-1.4.0/src/base64.rs +59 -0
  60. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/bindings/arguments.rs +6 -73
  61. hashcodecs-1.4.0/src/bindings/base64/api.rs +308 -0
  62. hashcodecs-1.4.0/src/bindings/base64/batch.rs +450 -0
  63. hashcodecs-1.4.0/src/bindings/base64/configured.rs +800 -0
  64. hashcodecs-1.4.0/src/bindings/base64/configured_tests.rs +911 -0
  65. hashcodecs-1.4.0/src/bindings/base64/decode.rs +648 -0
  66. hashcodecs-1.4.0/src/bindings/base64/encode.rs +679 -0
  67. hashcodecs-1.4.0/src/bindings/base64/lenient.rs +549 -0
  68. hashcodecs-1.4.0/src/bindings/base64/policy.rs +463 -0
  69. hashcodecs-1.4.0/src/bindings/base64/scan/aarch64.rs +112 -0
  70. hashcodecs-1.4.0/src/bindings/base64/scan/scalar.rs +60 -0
  71. hashcodecs-1.4.0/src/bindings/base64/scan/x86.rs +296 -0
  72. hashcodecs-1.4.0/src/bindings/base64/scan.rs +182 -0
  73. hashcodecs-1.4.0/src/bindings/base64/staging.rs +380 -0
  74. hashcodecs-1.4.0/src/bindings/base64/strict.rs +274 -0
  75. hashcodecs-1.4.0/src/bindings/base64.rs +14 -0
  76. hashcodecs-1.4.0/src/bindings/buffer.rs +750 -0
  77. hashcodecs-1.4.0/src/bindings/compatibility.rs +113 -0
  78. hashcodecs-1.4.0/src/bindings/murmur3/callbacks.rs +85 -0
  79. hashcodecs-1.4.0/src/bindings/murmur3/digest.rs +37 -0
  80. hashcodecs-1.4.0/src/bindings/murmur3/incremental.rs +123 -0
  81. hashcodecs-1.4.0/src/bindings/murmur3/methods.rs +20 -0
  82. hashcodecs-1.2.1/src/bindings/murmur3/mod.rs → hashcodecs-1.4.0/src/bindings/murmur3.rs +1 -1
  83. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/bindings/objects.rs +54 -35
  84. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/bindings/runtime.rs +3 -1
  85. hashcodecs-1.4.0/src/bindings/schema.rs +234 -0
  86. hashcodecs-1.4.0/src/bindings/xxhash/batch.rs +472 -0
  87. hashcodecs-1.4.0/src/bindings/xxhash/callbacks.rs +122 -0
  88. hashcodecs-1.4.0/src/bindings/xxhash/methods.rs +20 -0
  89. hashcodecs-1.4.0/src/bindings/xxhash.rs +5 -0
  90. hashcodecs-1.2.1/src/bindings/mod.rs → hashcodecs-1.4.0/src/bindings.rs +2 -0
  91. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/lib.rs +4 -5
  92. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/block_buffer.rs +7 -3
  93. hashcodecs-1.4.0/src/murmur3/dispatch.rs +53 -0
  94. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/primitives.rs +2 -3
  95. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/tests.rs +93 -63
  96. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/x64_128/x86.rs +29 -30
  97. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/x64_128.rs +53 -48
  98. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/x86_128/x86.rs +44 -36
  99. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/x86_128.rs +41 -41
  100. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/x86_32/x86.rs +25 -27
  101. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/x86_32.rs +43 -43
  102. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3.rs +2 -3
  103. hashcodecs-1.4.0/src/xxhash/batch.rs +543 -0
  104. {hashcodecs-1.2.1/src/xxhash/long → hashcodecs-1.4.0/src/xxhash/long_inputs}/aarch64.rs +49 -16
  105. hashcodecs-1.4.0/src/xxhash/long_inputs/scalar.rs +75 -0
  106. {hashcodecs-1.2.1/src/xxhash/long → hashcodecs-1.4.0/src/xxhash/long_inputs}/x86/avx2.rs +42 -20
  107. {hashcodecs-1.2.1/src/xxhash/long → hashcodecs-1.4.0/src/xxhash/long_inputs}/x86/avx2_batch.rs +21 -15
  108. {hashcodecs-1.2.1/src/xxhash/long → hashcodecs-1.4.0/src/xxhash/long_inputs}/x86/avx512.rs +20 -8
  109. {hashcodecs-1.2.1/src/xxhash/long → hashcodecs-1.4.0/src/xxhash/long_inputs}/x86/ssse3.rs +21 -8
  110. hashcodecs-1.2.1/src/xxhash/long.rs → hashcodecs-1.4.0/src/xxhash/long_inputs.rs +166 -138
  111. hashcodecs-1.4.0/src/xxhash/one_shot.rs +76 -0
  112. hashcodecs-1.4.0/src/xxhash/prepared.rs +136 -0
  113. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/xxhash/primitives.rs +47 -12
  114. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/xxhash/proofs.rs +13 -7
  115. hashcodecs-1.4.0/src/xxhash/short_inputs.rs +279 -0
  116. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/xxhash/tests.rs +182 -44
  117. hashcodecs-1.4.0/src/xxhash.rs +25 -0
  118. hashcodecs-1.4.0/tools/generate_api_metadata.py +412 -0
  119. hashcodecs-1.4.0/tools/install_local_wheel.py +30 -0
  120. hashcodecs-1.4.0/tools/verify_sdist.py +127 -0
  121. hashcodecs-1.2.1/CHANGELOG.md +0 -141
  122. hashcodecs-1.2.1/benches/xxhash.rs +0 -141
  123. hashcodecs-1.2.1/docs/ARCHITECTURE.md +0 -198
  124. hashcodecs-1.2.1/docs/benchmarks/base64-python-batch-large.svg +0 -85
  125. hashcodecs-1.2.1/docs/benchmarks/base64-python-batch-reusable.svg +0 -106
  126. hashcodecs-1.2.1/docs/benchmarks/base64-python-batch.svg +0 -313
  127. hashcodecs-1.2.1/docs/benchmarks/base64-python-lenient.svg +0 -127
  128. hashcodecs-1.2.1/docs/benchmarks/base64-python-memoryview.svg +0 -159
  129. hashcodecs-1.2.1/docs/benchmarks/base64-python-mutable.svg +0 -83
  130. hashcodecs-1.2.1/docs/benchmarks/base64-python-reusable.svg +0 -115
  131. hashcodecs-1.2.1/docs/benchmarks/base64-python.svg +0 -203
  132. hashcodecs-1.2.1/docs/benchmarks/base64-rust.svg +0 -203
  133. hashcodecs-1.2.1/docs/benchmarks/murmur3-python-mutable.svg +0 -169
  134. hashcodecs-1.2.1/docs/benchmarks/murmur3-python.svg +0 -235
  135. hashcodecs-1.2.1/docs/benchmarks/murmur3-rust.svg +0 -193
  136. hashcodecs-1.2.1/docs/benchmarks/performance-at-a-glance.svg +0 -37
  137. hashcodecs-1.2.1/docs/benchmarks/results.csv +0 -527
  138. hashcodecs-1.2.1/docs/benchmarks/xxh3-python.svg +0 -181
  139. hashcodecs-1.2.1/docs/benchmarks/xxh3-rust-batch-remainders.svg +0 -139
  140. hashcodecs-1.2.1/docs/benchmarks/xxh3-rust.svg +0 -169
  141. hashcodecs-1.2.1/docs/requirements.txt +0 -2
  142. hashcodecs-1.2.1/src/backend.rs +0 -241
  143. hashcodecs-1.2.1/src/base64/backend.rs +0 -94
  144. hashcodecs-1.2.1/src/base64/decode/aarch64.rs +0 -225
  145. hashcodecs-1.2.1/src/base64/decode/avx2.rs +0 -182
  146. hashcodecs-1.2.1/src/base64/decode/avx512.rs +0 -117
  147. hashcodecs-1.2.1/src/base64/decode/sse41.rs +0 -51
  148. hashcodecs-1.2.1/src/base64/dispatch.rs +0 -346
  149. hashcodecs-1.2.1/src/base64/encode/aarch64.rs +0 -113
  150. hashcodecs-1.2.1/src/base64/encode/avx512.rs +0 -132
  151. hashcodecs-1.2.1/src/base64/encode/ssse3.rs +0 -86
  152. hashcodecs-1.2.1/src/base64/encode.rs +0 -321
  153. hashcodecs-1.2.1/src/base64/output.rs +0 -17
  154. hashcodecs-1.2.1/src/base64.rs +0 -55
  155. hashcodecs-1.2.1/src/bindings/base64/callbacks.rs +0 -755
  156. hashcodecs-1.2.1/src/bindings/base64/decode/plan.rs +0 -176
  157. hashcodecs-1.2.1/src/bindings/base64/decode.rs +0 -1686
  158. hashcodecs-1.2.1/src/bindings/base64/encode.rs +0 -221
  159. hashcodecs-1.2.1/src/bindings/base64/methods.rs +0 -678
  160. hashcodecs-1.2.1/src/bindings/base64/mod.rs +0 -499
  161. hashcodecs-1.2.1/src/bindings/buffer.rs +0 -400
  162. hashcodecs-1.2.1/src/bindings/murmur3/digest.rs +0 -25
  163. hashcodecs-1.2.1/src/bindings/murmur3/incremental.rs +0 -383
  164. hashcodecs-1.2.1/src/bindings/murmur3/methods.rs +0 -103
  165. hashcodecs-1.2.1/src/bindings/murmur3/one_shot.rs +0 -86
  166. hashcodecs-1.2.1/src/bindings/xxhash/batch.rs +0 -270
  167. hashcodecs-1.2.1/src/bindings/xxhash/methods.rs +0 -201
  168. hashcodecs-1.2.1/src/bindings/xxhash/mod.rs +0 -195
  169. hashcodecs-1.2.1/src/murmur3/dispatch.rs +0 -51
  170. hashcodecs-1.2.1/src/xxhash/batch.rs +0 -282
  171. hashcodecs-1.2.1/src/xxhash/hash.rs +0 -71
  172. hashcodecs-1.2.1/src/xxhash/long/scalar.rs +0 -53
  173. hashcodecs-1.2.1/src/xxhash/short.rs +0 -177
  174. hashcodecs-1.2.1/src/xxhash.rs +0 -28
  175. hashcodecs-1.2.1/tools/generate_api_metadata.py +0 -235
  176. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/LICENSE +0 -0
  177. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/LICENSE-MIT +0 -0
  178. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/SECURITY.md +0 -0
  179. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/base64.md +0 -0
  180. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/compatibility.md +0 -0
  181. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/index.md +0 -0
  182. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/murmur3.md +0 -0
  183. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/docs/xxh3.md +0 -0
  184. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/hashcodecs/py.typed +0 -0
  185. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/base64/error.rs +0 -0
  186. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/miri_tests.rs +0 -0
  187. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/murmur3/proofs.rs +0 -0
  188. /hashcodecs-1.2.1/src/xxhash/long/x86/mod.rs → /hashcodecs-1.4.0/src/xxhash/long_inputs/x86.rs +0 -0
  189. {hashcodecs-1.2.1 → hashcodecs-1.4.0}/src/xxhash/miri_tests.rs +0 -0
@@ -10,6 +10,9 @@ site/
10
10
  .venv*/
11
11
  .coverage
12
12
  coverage.xml
13
+ *.profraw
14
+ *.lcov
15
+ *.log
13
16
 
14
17
  # These are backup files generated by rustfmt
15
18
  **/*.rs.bk
@@ -6,9 +6,13 @@ Pin one logical CPU. Run each case in one thread. Collect 50 Rust samples and 15
6
6
  baseline with AVX2, the backend that hashcodecs selects on this host. Higher throughput wins.
7
7
 
8
8
  Build the Python wheel with CPython 3.12 and the full C API. Keep competitor values from the latest comparison run.
9
- Use `uv run python benchmarks/render_charts.py` to render the charts. Read exact values in
9
+ Use `uv run --python 3.12 --no-project python benchmarks/render_charts.py` to render the charts. Read exact values in
10
10
  [docs/benchmarks/results.csv](docs/benchmarks/results.csv).
11
11
 
12
+ The standard and URL-safe Python decode panels report CPython 3.12.10 measurements from 2026-09-09; the lenient
13
+ decode chart retains its 2026-09-05 measurements. Each value is the median of 15 samples lasting at least 0.2
14
+ seconds each, with one logical CPU pinned.
15
+
12
16
  ## Timing Controls
13
17
 
14
18
  Every Python benchmark accepts `--samples` (default: 15) and `--minimum-sample-seconds` (default: 0.2). Their
@@ -16,12 +20,16 @@ sampling time per case is at least their product, plus calibration; use lower va
16
20
  hashcodecs-only pass, use `--hashcodecs-only --samples 3 --minimum-sample-seconds 0.05` with each Python benchmark
17
21
  script.
18
22
 
23
+ Each Rust Criterion harness collects 50 samples per case. Pass Criterion's `--sample-size` option for an exploratory
24
+ run with a different count.
25
+
19
26
  ## Python Call Costs
20
27
 
21
28
  Run `python benchmarks/python_calls.py` to measure positional calls from 0 through 256 bytes in nanoseconds per
22
29
  call. Use `--keywords` for positional and keyword calls at 64 bytes, or `--thresholds` for latency around the
23
30
  GIL-detachment cutoffs. The `--thread-scaling` mode measures aggregate throughput with one, two, and four threads;
24
- it does not pin the process to one logical CPU.
31
+ it does not pin the process to one logical CPU. Use `--buffer-inputs` to compare 64-byte and 4 KiB XXH3-64 calls
32
+ across bytes, full and sliced memoryviews, writable and non-contiguous views, and `array('B')`.
25
33
 
26
34
  ## XXH3
27
35
 
@@ -30,10 +38,38 @@ For Python, run the upstream `xxhash` extension beside hashcodecs. Pass 32 equal
30
38
  The Rust remainder cases pass two or three equal-size long inputs. Run Python remainder cases with
31
39
  `python benchmarks/python_xxhash.py --batch-counts 2 3`.
32
40
 
41
+ To measure a branch against its parent, build both extensions with the same Python and Rust toolchains, then run:
42
+
43
+ ```sh
44
+ uv run --frozen --no-sync python benchmarks/compare_xxh3_batches.py path/to/parent/_hashcodecs.pyd path/to/branch/_hashcodecs.pyd
45
+ ```
46
+
47
+ Use the corresponding `.so` paths on Linux or macOS. The comparison loads both builds into one interpreter, pins
48
+ one CPU, and alternates their timing order across 15 samples. It checks matching digests and covers bytes,
49
+ bytearrays, and writable memoryviews. Use `--batch-counts 2 9 32 33 --sizes 64` to inspect small batches and the
50
+ 32-result stack boundary. Positive `change_percent` values mean higher branch throughput.
51
+
52
+ The [32-item parent comparison](docs/benchmarks/xxh3-batch-parent-comparison.csv) records CPython 3.12.10 results
53
+ against parent commit `f17ab86`, measured on 2026-09-05. These paired measurements also cover the 256 KiB
54
+ GIL-detachment threshold and 1 MiB items. The Python XXH3 chart uses the candidate's allocating-batch measurements;
55
+ packed-output and upstream values retain their prior measurements.
56
+
57
+ Across the 30 paired 32-item cases, branch throughput ranges from 2.59% lower to 2.70% higher than the parent.
58
+ The [stack-boundary comparison](docs/benchmarks/xxh3-batch-boundary-comparison.csv) covers counts 2 and 33 with
59
+ 64-byte items: two-item bytearray batches lose 5.40–6.05%, and 33-item bytes batches lose 6.06–7.05%. These
60
+ measurements show residual overhead for some small-input batches; they do not establish zero regression.
61
+
62
+ The Rust mixed benchmarks use `[1024, 1024, 4096, 4096]`, `[257, 258, 259, 260]`, `[240, 240, 241, 241]`, and the
63
+ reverse boundary order. The 1024/4096 case measures adjacent two-item long runs. The 257–260 case measures a
64
+ four-item run with one shared stripe count and distinct final stripes. The 240/241 cases measure both orders across
65
+ the short/long dispatch boundary.
66
+
33
67
  Use the focused one-shot run to cover the AVX2 four-chain boundaries:
34
68
 
35
69
  ```sh
36
- cargo bench --bench xxhash -- --sample-size 50 "xxh3_(64|128)/(241|512|768|1024|1536|2048|4096)/hashcodecs"
70
+ cargo bench --manifest-path benches/Cargo.toml --bench xxhash -- "xxh3_(64|128)/(240|241|512|768|1024|1536|2048|4096)/hashcodecs"
71
+ cargo bench --manifest-path benches/Cargo.toml --bench xxhash -- "xxh3_batch/mixed/.*/hashcodecs_(64|128)"
72
+ cargo bench --manifest-path benches/Cargo.toml --bench xxhash -- "xxh3_prepared"
37
73
  ```
38
74
 
39
75
  [![Rust XXH3 throughput](docs/benchmarks/xxh3-rust.svg)](docs/benchmarks/xxh3-rust.svg)
@@ -55,11 +91,17 @@ noisy cases insert `!` at the same boundaries. Both cases measure returned bytes
55
91
 
56
92
  [![Lenient Python Base64 throughput](docs/benchmarks/base64-python-lenient.svg)](docs/benchmarks/base64-python-lenient.svg)
57
93
 
94
+ ## Wrapped Python Base64
95
+
96
+ Run `python benchmarks/python_base64.py --wrapped` with CPython 3.15 or newer. The benchmark inserts newlines after
97
+ 76 output characters and measures returned bytes and a reusable `bytearray`.
98
+
58
99
  ## Python Memoryview Inputs
59
100
 
60
- Use `--memoryview-input` for full immutable views and `--sliced-memoryview-input` for equal-length views with a
61
- nonzero starting offset. The latter covers the copy/stabilization path used by slices while keeping the encoded data
62
- identical.
101
+ Use `--memoryview-input` for full immutable views and `--sliced-memoryview-input` for equal-length contiguous views
102
+ with a nonzero starting offset. Full views can recover their exact immutable owner at detachment sizes; slices cover
103
+ offset-buffer handling, which borrows under the GIL and stabilizes the input in free-threaded builds. The encoded data
104
+ remains identical.
63
105
 
64
106
  [![Python Base64 memoryview inputs](docs/benchmarks/base64-python-memoryview.svg)](docs/benchmarks/base64-python-memoryview.svg)
65
107
 
@@ -76,6 +118,15 @@ into a decode investigation:
76
118
  python benchmarks/python_base64_batch.py --item-sizes 4096 --batch-sizes 512 768 1024 1280 2048 --decode-only
77
119
  ```
78
120
 
121
+ Add `--memoryview-input` to wrap every matrix input in an exact memoryview. This mode compares independent views
122
+ against the matching one-item loops and reusable-output paths.
123
+
124
+ [![Python Base64 memoryview batch throughput](docs/benchmarks/base64-python-batch-memoryview.svg)](docs/benchmarks/base64-python-batch-memoryview.svg)
125
+
126
+ ```sh
127
+ python benchmarks/python_base64_batch.py --item-sizes 1048576 --batch-sizes 8 --memoryview-input --decode-only
128
+ ```
129
+
79
130
  Use a single operation when recording a sampling profile, or compare traced allocations without a sampler:
80
131
 
81
132
  ```sh
@@ -118,3 +169,27 @@ Pass `bytearray` inputs to the Base64 API.
118
169
  Pass `bytearray` inputs to the MurmurHash3 API.
119
170
 
120
171
  [![Mutable Python MurmurHash3 inputs](docs/benchmarks/murmur3-python-mutable.svg)](docs/benchmarks/murmur3-python-mutable.svg)
172
+
173
+ ## Reproduction
174
+
175
+ Run the benchmark
176
+
177
+ ```
178
+ uv sync --python 3.12 --frozen --group benchmark --no-install-project
179
+
180
+ uv run --python 3.12 --refresh-package hashcodecs --no-project --with . --with mmh3==5.2.1 --with pybase64==1.4.3 --with xxhash==3.8.1 python benchmarks/python_base64.py --hashcodecs-only
181
+
182
+ uv run --python 3.12 --refresh-package hashcodecs --no-project --with . --with mmh3==5.2.1 --with pybase64==1.4.3 --with xxhash==3.8.1 python benchmarks/python_base64_batch.py --hashcodecs-only
183
+
184
+ uv run --python 3.12 --refresh-package hashcodecs --no-project --with . --with mmh3==5.2.1 --with pybase64==1.4.3 --with xxhash==3.8.1 python benchmarks/python_murmur3.py --hashcodecs-only
185
+
186
+ uv run --python 3.12 --refresh-package hashcodecs --no-project --with . --with mmh3==5.2.1 --with pybase64==1.4.3 --with xxhash==3.8.1 python benchmarks/python_murmur3.py --hashcodecs-only --incremental
187
+
188
+ uv run --python 3.12 --refresh-package hashcodecs --no-project --with . --with mmh3==5.2.1 --with pybase64==1.4.3 --with xxhash==3.8.1 python benchmarks/python_xxhash.py --hashcodecs-only
189
+ ```
190
+
191
+ Update the documentation
192
+
193
+ ```
194
+ uv run --python 3.12 --no-project python benchmarks/render_charts.py
195
+ ```
@@ -0,0 +1,209 @@
1
+ # Changelog
2
+
3
+ This file records notable user-facing changes to `hashcodecs`. Version 1.0.0 starts the stable Python API policy.
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [1.4.0] - 2026-09-10
8
+
9
+ ### What's Changed
10
+ * refactor: flatten internal module layout by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/91
11
+ * refactor: prepare Base64 decoder policies once by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/92
12
+ * refactor: consolidate binding and dispatch cleanup by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/93
13
+ * refactor: simplify project module layout by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/94
14
+ * refactor: prepare codec policies and unify bindings by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/95
15
+ * refactor: accelerate Base64 codec hot paths by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/96
16
+ * fix: protect XXH3 batches from GC reentrancy by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/97
17
+ * refactor: unify Base64 decode execution by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/98
18
+ * refactor: flatten Base64 binding ownership by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/99
19
+ * refactor: improve XXH3 loads and internal naming by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/100
20
+ * refactor: reduce Base64 decoder setup and retry costs by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/101
21
+ * fix: preserve Base64 decode boundaries and restore ARM coverage by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/102
22
+ * refactor: keep XXH3 AVX2 tail chains in registers by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/103
23
+ * refactor: store AVX2 Base64 vectors in smaller groups by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/104
24
+ * fix: reduce Python overhead and align canonical decoding by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/106
25
+ * refactor: reduce cached AVX2 encoder setup by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/107
26
+ * feat: optimize XXH3 seeded and batch hashing by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/108
27
+ * Optimize AVX2 Base64 decoding by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/109
28
+ * refactor: optimize Python batch orchestration by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/110
29
+ * feat: optimize XXH3 batches and wrapped Base64 by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/111
30
+ * Fuse Base64 SIMD lookup paths and Murmur3 hex output by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/112
31
+ * fix: preserve custom alphabets and batch typing by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/113
32
+
33
+
34
+ **Full Changelog**: https://github.com/kozistr/hashcodecs-rs/compare/v1.3.0...v1.4.0
35
+
36
+ ## [1.3.0] - 2026-09-04
37
+
38
+ ### What's Changed
39
+ * chore: expand XXH3 benchmark coverage by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/61
40
+ * refactor: split Base64 decoder bindings by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/62
41
+ * refactor: declare Base64 binding schema by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/63
42
+ * perf: inspect exact CPython memoryviews directly by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/64
43
+ * refactor: avoid copying Base64 fallback inputs by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/65
44
+ * chore: strengthen runtime coverage and benchmarks by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/66
45
+ * fix: avoid unnecessary batch snapshots and scalar grouping by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/67
46
+ * refactor: generate Base64 binding metadata by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/68
47
+ * perf: remove advanced decode and batch allocations by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/69
48
+ * refactor: finish native codec cleanup by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/70
49
+ * chore: verify source distributions in CI by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/71
50
+ * fix: stabilize aliased Base64 decode inputs by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/72
51
+ * perf: remove Python batch input copies by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/73
52
+ * fix: use strict fast paths for decode-into by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/74
53
+ * refactor: streamline native bindings and benchmarks by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/75
54
+ * fix: restore XXH fast paths and wheel compatibility by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/76
55
+ * refactor: use four-lane AArch64 XXH3 accumulation by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/77
56
+ * refactor: clarify internal names and technical prose by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/78
57
+ * fix: restore Base64 batch encode throughput by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/79
58
+ * refactor: clarify internal naming by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/80
59
+ * refactor: simplify internal decode and dispatch paths by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/81
60
+ * fix: harden hashers and optimize codec paths by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/82
61
+ * refactor: centralize Python Base64 decode routing by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/83
62
+ * refactor: standardize Rust callback and input names by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/84
63
+ * refactor: clarify codec routing and CPU capabilities by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/85
64
+ * refactor: consolidate base64 batch ownership by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/86
65
+ * refactor: reduce XXH3 dispatch overhead by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/87
66
+ * Fix Base64 batch alias stabilization and AVX2 streaming stores by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/88
67
+ * fix: restore Base64 encode fast paths by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/89
68
+ * fix: restore Base64 memoryview batch throughput by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/90
69
+
70
+
71
+ **Full Changelog**: https://github.com/kozistr/hashcodecs-rs/compare/v1.2.1...v1.3.0
72
+
73
+ ## [1.2.1] - 2026-08-26
74
+
75
+ ### What's Changed
76
+ * fix: harden buffer and lenient decode paths by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/58
77
+ * Refactor Murmur SIMD and centralize XXH3 long dispatch by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/59
78
+ * Repair sdist verification and roll back unpublished 1.2.1 by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/60
79
+
80
+
81
+ **Full Changelog**: https://github.com/kozistr/hashcodecs-rs/compare/v1.2.0...v1.2.1
82
+
83
+ ## [1.2.0] - 2026-08-25
84
+
85
+ ### What's Changed
86
+ * fix: harden free-threaded bindings and API correctness by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/47
87
+ * feat: accelerate Python batch outputs by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/48
88
+ * feat: add native lenient Base64 decoding by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/49
89
+ * update: tune Python detach thresholds by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/50
90
+ * fix: harden Base64 binding edge cases by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/51
91
+ * fix: stabilize Base64 GIL release test by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/52
92
+ * feat: accelerate XXH3 batch remainders by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/53
93
+ * perf: refresh Base64 batch benchmarks by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/54
94
+ * perf: accelerate XXH3 long inputs by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/55
95
+ * perf: profile Base64 batch allocations by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/56
96
+ * refactor: organize Python binding infrastructure by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/57
97
+
98
+
99
+ **Full Changelog**: https://github.com/kozistr/hashcodecs-rs/compare/v1.1.0...v1.2.0
100
+
101
+ ## [1.1.0] - 2026-08-23
102
+
103
+ ### What's Changed
104
+ * chore: use trusted publishing for crates.io by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/44
105
+ * refactor: establish clean architecture boundaries by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/45
106
+ * feat: borrow contiguous Python buffers by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/46
107
+
108
+
109
+ **Full Changelog**: https://github.com/kozistr/hashcodecs-rs/compare/v1.0.0...v1.1.0
110
+
111
+ ## [1.0.0] - 2026-08-22
112
+
113
+ ### What's Changed
114
+ * Expand Python and Rust API documentation by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/36
115
+ * feat: move base64 batch aliases into Rust by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/37
116
+ * feat: support free-threaded Python wheels by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/38
117
+ * Update benchmark and Python support docs by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/39
118
+ * chore: reduce CI runner usage and latency by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/40
119
+ * build: prepare 1.0 release by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/41
120
+ * build: publish Rust crate from release workflow by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/42
121
+ * feat: expose namespaced Rust API by @kozistr in https://github.com/kozistr/hashcodecs-rs/pull/43
122
+
123
+
124
+ **Full Changelog**: https://github.com/kozistr/hashcodecs-rs/compare/v0.6.1...v1.0.0
125
+
126
+ ## [0.6.1] - 2026-08-22
127
+
128
+ ### Added
129
+
130
+ - Reusable output buffers for XXH3 batch operations.
131
+ - A Read the Docs site with Python and Rust API documentation.
132
+
133
+ ## [0.6.0] - 2026-08-21
134
+
135
+ ### Added
136
+
137
+ - SIMD-accelerated XXH3-64 and XXH3-128 APIs.
138
+ - Native one-shot and batch bindings built on the full CPython API.
139
+
140
+ ### Changed
141
+
142
+ - Faster Base64 and XXH3 hot paths, including small XXH3 inputs and large AVX2 Base64 inputs.
143
+ - One runtime dispatch layer now selects SIMD backends for each codec and hash implementation.
144
+
145
+ ## [0.5.0] - 2026-08-12
146
+
147
+ ### Added
148
+
149
+ - Batch Base64 APIs that write into caller-provided buffers.
150
+
151
+ ### Changed
152
+
153
+ - Faster unpadded Base64 and Python decoding paths with fewer aligned-input copies.
154
+ - Release validation now runs before packaging and publication.
155
+
156
+ ## [0.4.0] - 2026-08-10
157
+
158
+ ### Added
159
+
160
+ - CPython 3.15 support.
161
+ - Native Base64 batch APIs.
162
+
163
+ ### Changed
164
+
165
+ - Faster SIMD Base64 codecs and mutable Python buffer handling.
166
+ - Simpler URL-safe Base64 wrappers.
167
+
168
+ ## [0.3.0] - 2026-08-09
169
+
170
+ ### Added
171
+
172
+ - Reusable Python output buffers for allocation-sensitive Base64 operations.
173
+
174
+ ### Changed
175
+
176
+ - Faster AVX2 Base64 decoding and SIMD encoding paths.
177
+
178
+ ## [0.2.0] - 2026-08-09
179
+
180
+ ### Added
181
+
182
+ - Incremental MurmurHash3 hashers.
183
+ - SIMD implementations for each MurmurHash3 variant and additional codec backends.
184
+
185
+ ### Fixed
186
+
187
+ - Short NEON Base64 blocks and scalar backend detection on non-x86 systems.
188
+
189
+ ## [0.1.0] - 2026-08-09
190
+
191
+ ### Added
192
+
193
+ - Initial Python and Rust APIs for Base64 and MurmurHash3.
194
+ - Runtime SIMD dispatch and platform-specific CPython wheels.
195
+
196
+ [Unreleased]: https://github.com/kozistr/hashcodecs-rs/compare/v1.4.0...HEAD
197
+ [1.4.0]: https://github.com/kozistr/hashcodecs-rs/compare/v1.3.0...v1.4.0
198
+ [1.3.0]: https://github.com/kozistr/hashcodecs-rs/compare/v1.2.1...v1.3.0
199
+ [1.2.1]: https://github.com/kozistr/hashcodecs-rs/compare/v1.2.0...v1.2.1
200
+ [1.2.0]: https://github.com/kozistr/hashcodecs-rs/compare/v1.1.0...v1.2.0
201
+ [1.1.0]: https://github.com/kozistr/hashcodecs-rs/compare/v1.0.0...v1.1.0
202
+ [1.0.0]: https://github.com/kozistr/hashcodecs-rs/compare/v0.6.1...v1.0.0
203
+ [0.6.1]: https://github.com/kozistr/hashcodecs-rs/compare/v0.6.0...v0.6.1
204
+ [0.6.0]: https://github.com/kozistr/hashcodecs-rs/compare/v0.5.0...v0.6.0
205
+ [0.5.0]: https://github.com/kozistr/hashcodecs-rs/compare/v0.4.0...v0.5.0
206
+ [0.4.0]: https://github.com/kozistr/hashcodecs-rs/compare/v0.3.0...v0.4.0
207
+ [0.3.0]: https://github.com/kozistr/hashcodecs-rs/compare/v0.2.0...v0.3.0
208
+ [0.2.0]: https://github.com/kozistr/hashcodecs-rs/compare/v0.1.0...v0.2.0
209
+ [0.1.0]: https://github.com/kozistr/hashcodecs-rs/tree/v0.1.0
@@ -5,8 +5,8 @@ authors:
5
5
  given-names: Hyeongchan
6
6
  orcid: https://orcid.org/0000-0002-1729-0580
7
7
  title: "hashcodecs: SIMD-accelerated Base64, MurmurHash3, and XXH3 for Python and Rust"
8
- version: 1.2.1
9
- date-released: 2026-08-26
8
+ version: 1.4.0
9
+ date-released: 2026-09-10
10
10
  license: "MIT OR Apache-2.0"
11
11
  repository-code: "https://github.com/kozistr/hashcodecs-rs"
12
12
  url: "https://github.com/kozistr/hashcodecs-rs"
@@ -194,21 +194,32 @@ dependencies = [
194
194
 
195
195
  [[package]]
196
196
  name = "hashcodecs"
197
- version = "1.2.1"
197
+ version = "1.4.0"
198
+ dependencies = [
199
+ "base64",
200
+ "memchr",
201
+ "mimalloc",
202
+ "murmur3",
203
+ "pyo3",
204
+ "pyo3-build-config",
205
+ "xxhash-c-sys",
206
+ "xxhash-rust",
207
+ ]
208
+
209
+ [[package]]
210
+ name = "hashcodecs-benchmarks"
211
+ version = "0.0.0"
198
212
  dependencies = [
199
213
  "base64",
200
214
  "base64-turbo",
201
215
  "criterion",
202
216
  "fastmurmur3",
203
- "memchr",
217
+ "hashcodecs",
204
218
  "mimalloc",
205
219
  "mm3h",
206
220
  "murmur3",
207
221
  "murmurs",
208
- "pyo3",
209
- "pyo3-build-config",
210
222
  "xxhash-c-sys",
211
- "xxhash-rust",
212
223
  ]
213
224
 
214
225
  [[package]]
@@ -1,8 +1,9 @@
1
1
  [package]
2
2
  name = "hashcodecs"
3
- version = "1.2.1"
3
+ version = "1.4.0"
4
4
  edition = "2024"
5
5
  rust-version = "1.89"
6
+ autobenches = false
6
7
  description = "SIMD-accelerated Base64 codecs and fast MurmurHash3 and xxHash implementations"
7
8
  license = "MIT OR Apache-2.0"
8
9
  repository = "https://github.com/kozistr/hashcodecs-rs"
@@ -10,6 +11,7 @@ keywords = ["base64", "simd", "murmur3", "xxhash", "python"]
10
11
  categories = ["encoding", "algorithms"]
11
12
  readme = "README.md"
12
13
  include = [
14
+ "/generated/**",
13
15
  "/src/**",
14
16
  "/benches/**",
15
17
  "/tests/sanitizers.rs",
@@ -19,6 +21,11 @@ include = [
19
21
  "/LICENSE-MIT",
20
22
  ]
21
23
 
24
+ [workspace]
25
+ members = [".", "benches"]
26
+ default-members = ["."]
27
+ resolver = "3"
28
+
22
29
  [lib]
23
30
  name = "hashcodecs"
24
31
  crate-type = ["rlib", "cdylib"]
@@ -37,28 +44,10 @@ pyo3-build-config = { version = "0.29.2", optional = true }
37
44
 
38
45
  [dev-dependencies]
39
46
  base64 = "=0.23.1"
40
- base64-turbo = "=0.3.0"
41
- criterion = { version = "=0.8.2", default-features = false, features = ["cargo_bench_support"] }
42
- fastmurmur3 = "=0.2.0"
43
- mimalloc = "=0.1.52"
44
- mm3h = "=0.1.3"
45
47
  murmur3 = "=0.5.2"
46
- murmurs = "=1.0.5"
47
48
  xxhash-c-sys = "=0.8.7"
48
49
  xxhash-rust = { version = "=0.8.18", features = ["xxh3"] }
49
50
 
50
- [[bench]]
51
- name = "base64"
52
- harness = false
53
-
54
- [[bench]]
55
- name = "murmur3"
56
- harness = false
57
-
58
- [[bench]]
59
- name = "xxhash"
60
- harness = false
61
-
62
51
  [[test]]
63
52
  name = "sanitizers"
64
53
  path = "tests/sanitizers.rs"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: hashcodecs
3
- Version: 1.2.1
3
+ Version: 1.4.0
4
4
  Summary: SIMD-accelerated Base64, MurmurHash3, and xxHash codecs
5
5
  Project-URL: Documentation, https://hashcodecs-rs.readthedocs.io/
6
6
  Project-URL: Repository, https://github.com/kozistr/hashcodecs-rs
@@ -43,20 +43,20 @@ Description-Content-Type: text/markdown
43
43
 
44
44
  <p align="center">
45
45
  <a href="BENCHMARK.md">
46
- <img src="docs/benchmarks/performance-at-a-glance.svg" alt="CPython 3.12 URL-safe Base64 encoding and decoding benchmark">
46
+ <img src="docs/benchmarks/performance-at-a-glance.svg" alt="CPython 3.12 standard Base64 encoding and decoding benchmark">
47
47
  </a>
48
48
  </p>
49
49
 
50
50
  SIMD-accelerated Base64, MurmurHash3, and XXH3 for Python and Rust.
51
51
 
52
52
  Move byte-heavy work into Rust without changing your Python inputs. `hashcodecs` accepts `bytes`, `bytearray`, and
53
- `memoryview`, selects the best available SIMD backend, and exposes batch and reusable-buffer APIs.
53
+ `memoryview`, selects the highest-priority supported SIMD backend, and exposes batch and reusable-buffer APIs.
54
54
 
55
55
  ## Features
56
56
 
57
57
  - Base64 encode and decode with standard, URL-safe, padded, unpadded, wrapped, and canonical modes.
58
58
  - MurmurHash3 x86-32, x86-128, and x64-128 with one-shot and incremental APIs.
59
- - Bit-for-bit compatible XXH3-64 and XXH3-128 with one-shot and native batch APIs.
59
+ - Bit-for-bit compatible XXH3-64 and XXH3-128 with prepared seeds and allocating and allocation-free native batch APIs.
60
60
  - Caller-managed `*_into` outputs for allocation-sensitive workloads.
61
61
  - Runtime dispatch across AVX-512, AVX2, SSE4.1, SSSE3, NEON, and scalar implementations where applicable.
62
62
  - Direct CPython buffer handling for `bytes`, `bytearray`, and `memoryview` inputs.
@@ -146,17 +146,36 @@ assert_eq!(
146
146
  hashcodecs::xxhash::xxh3_64(b"", 0),
147
147
  0x2d06_8005_38d3_94c2
148
148
  );
149
+
150
+ let seeded_input = vec![7; 1024];
151
+ let prepared = hashcodecs::xxhash::PreparedXxh3::new(42);
152
+ assert_eq!(
153
+ prepared.hash_64(&seeded_input),
154
+ hashcodecs::xxhash::xxh3_64(&seeded_input, 42)
155
+ );
156
+
157
+ let inputs: &[&[u8]] = &[b"hello", b"world"];
158
+ assert_eq!(
159
+ prepared.hash_64_batch(inputs),
160
+ hashcodecs::xxhash::xxh3_64_batch(inputs, 42)
161
+ );
162
+ let mut hashes = [0_u64; 2];
163
+ let mut index = 0;
164
+ hashcodecs::xxhash::xxh3_64_batch_for_each(inputs, 0, |hash| {
165
+ hashes[index] = hash;
166
+ index += 1;
167
+ });
168
+ assert_eq!(index, inputs.len());
149
169
  ```
150
170
 
151
171
  ## Architecture
152
172
 
153
- The Rust core owns algorithm behavior and SIMD dispatch. A substantial CPython layer handles argument parsing, buffer
154
- ownership, reusable outputs, and GIL decisions; root-level Python modules provide typed public exports without
155
- adding per-call wrappers.
173
+ The Rust core owns algorithm behavior and SIMD dispatch. The CPython layer handles argument parsing, buffers,
174
+ reusable outputs, and GIL decisions. Root-level Python modules provide typed exports without per-call wrappers.
156
175
 
157
- Each Rust algorithm exposes a small public façade. Base64 groups internals by encode and decode operation and
176
+ Each Rust algorithm exposes a small public module. Base64 groups internals by encode and decode operation and
158
177
  places ISA kernels such as `encode/avx2.rs` and `decode/ssse3.rs` under their operation. MurmurHash3 groups code by
159
- canonical variant. XXH3 uses processing-stage modules, with long-input ISA kernels under `xxhash/long/`.
178
+ canonical variant. XXH3 uses processing-stage modules. Long-input ISA kernels are under `xxhash/long_inputs/`.
160
179
 
161
180
  See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the module layout, dispatch model, algorithm data flows,
162
181
  CPython boundary, and safety invariants.
@@ -206,9 +225,10 @@ Read the focused cases, commands, and values in [BENCHMARK.md](BENCHMARK.md). Re
206
225
  Comparison crates and Python packages are development-only dependencies and are not included in consumer builds.
207
226
 
208
227
  ```sh
209
- cargo bench --bench base64
210
- cargo bench --bench murmur3
211
- cargo bench --bench xxhash
228
+ cargo bench --manifest-path benches/Cargo.toml --bench base64
229
+ cargo bench --manifest-path benches/Cargo.toml --bench murmur3
230
+ cargo bench --manifest-path benches/Cargo.toml --bench xxhash
231
+ cargo bench --manifest-path benches/Cargo.toml --bench crossover
212
232
 
213
233
  uv sync --group benchmark --no-install-project
214
234
  uv run --no-project --with . python benchmarks/python_base64.py
@@ -219,22 +239,24 @@ uv run --no-project --with . python benchmarks/python_xxhash.py
219
239
  ```
220
240
 
221
241
  The Python benchmarks expose focused modes such as `--into`, `--lenient`, `--bytearray-input`, `--memoryview-input`,
222
- `--sliced-memoryview-input`, `--incremental`, `--large`, and `--hashcodecs-only`. All scripts also accept `--samples` and
223
- `--minimum-sample-seconds`; use `--help` on a benchmark script for its supported modes and defaults.
242
+ `--sliced-memoryview-input`, `--buffer-inputs`, `--incremental`, `--large`, and `--hashcodecs-only`. All scripts also
243
+ accept `--samples` and `--minimum-sample-seconds`; use `--help` on a benchmark script for its supported modes and
244
+ defaults.
224
245
 
225
246
  For the same-ISA Windows XXH3 comparison shown above, rebuild the C baseline with:
226
247
 
227
248
  ```powershell
228
249
  $env:CFLAGS='/O2 /arch:AVX2'
229
250
  cargo clean -p xxhash-c-sys
230
- cargo bench --bench xxhash
251
+ cargo bench --manifest-path benches/Cargo.toml --bench xxhash
231
252
  ```
232
253
 
233
254
  ## Performance snapshot
234
255
 
235
- In the full 2026-08-23 hashcodecs-only run on the benchmark host, `hashcodecs.xxh3_64` processes a 1 MiB input at
236
- 79.20 GiB/s. With 256 B items in batches of 64, the Base64 batch API reaches 8.80 GiB/s for encode and 7.58 GiB/s for
237
- decode. The run pins one logical CPU and uses 15 samples with a 0.2-second minimum per sample. Read the
256
+ In the focused 2026-09-09 hashcodecs-only run on the benchmark host, `hashcodecs.xxh3_64` processes a 1 MiB input
257
+ at 91.27 GiB/s. In the full 2026-09-02 run, the Base64 batch API reaches 11.84 GiB/s for encode and 6.23 GiB/s for
258
+ decode with 256 B items in batches of 64. Each run pins one logical CPU and uses 15 samples with a 0.2-second
259
+ minimum per sample. Read the
238
260
  [benchmark details](BENCHMARK.md) and [raw comparison results](docs/benchmarks/results.csv).
239
261
 
240
262
  ## Development
@@ -248,14 +270,12 @@ uv build
248
270
  Run the primary local checks:
249
271
 
250
272
  ```sh
251
- cargo fmt --check
252
- cargo clippy --all-targets --features python -- -D warnings
253
- cargo test --features python
254
- uv run --frozen --no-sync ruff check . --no-cache
255
- uv run --frozen --no-sync ruff format --check .
256
- uv run --frozen --no-sync pytest tests --cov=hashcodecs --cov-branch --cov-fail-under=100
273
+ just check
257
274
  ```
258
275
 
276
+ `just check` builds and reinstalls the current wheel before running Python tests. Run `just full-check` before
277
+ committing to also check release builds, Rust core coverage, and the extracted source distribution.
278
+
259
279
  Optimized paths are also checked with differential fuzzing, Kani, strict-provenance Miri, AddressSanitizer, and
260
280
  MemorySanitizer in CI.
261
281