Skip to content

Speed up batch scans and Python calls - #53

Merged
mrecachinas merged 9 commits into
mainfrom
perf/theoretical-floor
Jul 10, 2026
Merged

Speed up batch scans and Python calls#53
mrecachinas merged 9 commits into
mainfrom
perf/theoretical-floor

Conversation

@mrecachinas

Copy link
Copy Markdown
Owner

Why

For small inputs, the Hamming-distance calculation itself is already extremely fast. Most of the remaining time was being spent around it: setting up Python buffers, checking the selected algorithm repeatedly, or creating too many parallel tasks for batch scans.

This PR removes that avoidable work while preserving the existing API and results.

What changed

  • Batch searches do less work. A best search stops as soon as it finds an exact match, and large scans use four coarse Rayon jobs instead of oversubscribing every CPU.
  • Python calls take a shorter path. Exact bytes inputs bypass the general buffer protocol, and small generic buffers avoid an unnecessary GIL release/reacquire cycle.
  • ARM hot paths exit earlier. Hex threshold checks inspect the first useful blocks sooner, and AArch64 uses LLVM’s faster native byte loop by default.
  • Benchmarks and documentation are current. The README records the measured M4 Max results and explains where Python overhead still dominates.

Representative results

Measured on an Apple M4 Max using three independent runs:

Workload Before After Improvement
Rust 512×16 best, exact match first 1,594 ns 8.2 ns 99.5%
Rust 16,384×64 best 213.3 µs 67.2 µs 68.5%
Rust 16,384×64 all 205.5 µs 76.9 µs 62.6%
Rust 100,000×128 best 330.1 µs 49.6 µs 85.0%
Python 64-byte distance 105.4 ns 46.6 ns 55.8%
Python 512×16 best, exact match first 1,958 ns 75.4 ns 96.1%

The single-record Rust kernels are now close to their practical hardware floors. PR #52 builds on this branch to address the remaining measured overhead in array dispatch, generic Python buffers, and concurrency thresholds.

Safety and compatibility

  • No public API changes.
  • Array ordering and lowest-index tie behavior are preserved.
  • Large Python operations still release the GIL so other threads can run.
  • Unsupported SIMD paths continue to use the existing fallbacks.

Testing

  • cargo test --no-default-features
  • cargo fmt --check
  • ruff check .
  • ruff format --check .
  • python -m pytest -vls .
  • Three Criterion benchmark passes
  • Three pytest-benchmark passes

mrecachinas and others added 9 commits July 9, 2026 21:51
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e7b02886-a2c5-43cd-bb97-bfa037d3b625
@github-actions

Copy link
Copy Markdown

📊 Benchmark Comparison Results

Status Benchmark Base PR Delta
⚠️ check_bytes_arrays_first_within_dist[16384 elems,s=64,end] 0.1288ms 0.1440ms 11.8% slower
⚠️ check_bytes_arrays_first_within_dist[16384 elems,s=64,mid] 0.0646ms 0.0718ms 11.2% slower
check_bytes_arrays_best_within_dist[ 512 elems,s=16,at 0] 0.0053ms 0.0001ms 97.6% faster
check_bytes_arrays_best_within_dist[ 512 elems,s=16,mid] 0.0050ms 0.0024ms 51.5% faster
➖ 41 benchmarks within noise (click to expand)
Benchmark Base PR Delta
check_bytes_arrays_all_within_dist[ 512 elems,s=16,at 0] 0.0039ms 0.0042ms 9.3% slower
check_bytes_arrays_all_within_dist[ 512 elems,s=16,end] 0.0039ms 0.0043ms 9.2% slower
check_bytes_arrays_all_within_dist[ 512 elems,s=16,mid] 0.0039ms 0.0043ms 9.5% slower
check_bytes_arrays_all_within_dist[ 1024 elems,s=32,at 0] 0.0083ms 0.0092ms 10.1% slower
check_bytes_arrays_all_within_dist[ 1024 elems,s=32,end] 0.0083ms 0.0092ms 9.9% slower
check_bytes_arrays_all_within_dist[ 1024 elems,s=32,mid] 0.0084ms 0.0092ms 9.8% slower
check_bytes_arrays_all_within_dist[16384 elems,s=64,at 0] 0.0878ms 0.0785ms 10.5% faster
check_bytes_arrays_all_within_dist[16384 elems,s=64,end] 0.0889ms 0.0786ms 11.6% faster
check_bytes_arrays_all_within_dist[16384 elems,s=64,mid] 0.0877ms 0.0782ms 10.9% faster
check_bytes_arrays_best_within_dist[ 512 elems,s=16,end] 0.0046ms 0.0048ms 3.2% slower
check_bytes_arrays_best_within_dist[ 1024 elems,s=32,at 0] 0.0098ms 0.0100ms 1.7% slower
check_bytes_arrays_best_within_dist[ 1024 elems,s=32,end] 0.0099ms 0.0100ms 1.8% slower
check_bytes_arrays_best_within_dist[ 1024 elems,s=32,mid] 0.0099ms 0.0100ms 1.6% slower
check_bytes_arrays_best_within_dist[16384 elems,s=64,at 0] 0.0957ms 0.0864ms 9.8% faster
check_bytes_arrays_best_within_dist[16384 elems,s=64,end] 0.0946ms 0.0858ms 9.3% faster
check_bytes_arrays_best_within_dist[16384 elems,s=64,mid] 0.0953ms 0.0859ms 9.9% faster
check_bytes_arrays_first_within_dist[ 512 elems,s=16,at 0] 0.0002ms 0.0001ms 54.5% faster
check_bytes_arrays_first_within_dist[ 512 elems,s=16,end] 0.0041ms 0.0045ms 8.2% slower
check_bytes_arrays_first_within_dist[ 512 elems,s=16,mid] 0.0022ms 0.0023ms 2.1% slower
check_bytes_arrays_first_within_dist[ 1024 elems,s=32,at 0] 0.0002ms 0.0001ms 55.1% faster
check_bytes_arrays_first_within_dist[ 1024 elems,s=32,end] 0.0089ms 0.0097ms 9.2% slower
check_bytes_arrays_first_within_dist[ 1024 elems,s=32,mid] 0.0046ms 0.0049ms 7.2% slower
check_bytes_arrays_first_within_dist[16384 elems,s=64,at 0] 0.0002ms 0.0002ms 0.8% slower
check_bytes_within_dist[127 bytes,d=500] 0.0002ms 0.0001ms 53.8% faster
check_bytes_within_dist[16 bytes,d=0] 0.0002ms 0.0001ms 54.1% faster
check_bytes_within_dist[64 bytes,d=100] 0.0002ms 0.0001ms 58.0% faster
hex_within_dist 0.0001ms 0.0001ms 6.0% faster
hd_bytes[1000-diff] 0.0002ms 0.0001ms 43.2% faster
hd_bytes[1000-same] 0.0002ms 0.0001ms 37.7% faster
hd_bytes[1024-diff] 0.0002ms 0.0001ms 44.2% faster
hd_bytes[1024-same] 0.0002ms 0.0001ms 41.7% faster
hd_bytes[3-diff] 0.0001ms 0.0001ms 46.3% faster
hd_bytes[3-same] 0.0001ms 0.0001ms 43.3% faster
hd_bytes[64-diff] 0.0001ms 0.0001ms 43.3% faster
hd_string[1000-diff] 0.0003ms 0.0002ms 35.2% faster
hd_string[1000-same] 0.0002ms 0.0002ms 1.0% slower
hd_string[1024-diff] 0.0002ms 0.0002ms 2.0% slower
hd_string[1024-same] 0.0002ms 0.0002ms 13.7% slower
hd_string[3-diff] 0.0002ms 0.0002ms no change
hd_string[3-same] 0.0001ms 0.0001ms 5.1% faster
hd_string[64-diff] 0.0001ms 0.0001ms 3.6% slower

Legend: ✅ Faster (>5%) · ⚠️ Slower (5-30%) · ❌ Regression (>30%) · 🆕 New · 🗑️ Removed

@mrecachinas
mrecachinas merged commit 392ba1b into main Jul 10, 2026
23 checks passed
@mrecachinas
mrecachinas deleted the perf/theoretical-floor branch July 10, 2026 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant