Skip to content

perf(codec): dict-band hot-path — slice header parse, dms-walk floor, SIMD prefix leading word#458

Merged
polaz merged 3 commits into
mainfrom
perf/dict-band-hotpath
Jun 30, 2026
Merged

perf(codec): dict-band hot-path — slice header parse, dms-walk floor, SIMD prefix leading word#458
polaz merged 3 commits into
mainfrom
perf/dict-band-hotpath

Conversation

@polaz

@polaz polaz commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary

Two hot-path improvements for the per-label-dictionary band (the CoordiNode
target), one on each side of the codec. Both are byte-identical and mirror the
shape of the upstream C reference for the same path.

Slice-direct header parse on the dict-handle decode path

decode_all_with_dict_handle still routed its per-frame header read through the
Read-trait dict reset (per-field read_exact via the io::impls shim) while
the non-dict decode_all already parsed the header straight from the input
slice. Add reset_from_slice_with_dict_handle (the slice-direct analog of the
Read-based dict reset) and wire decode_all_with_dict_handle through it. On
decompress-dict/level_12_lazy/small-10k-random this is -2.4 % (i9,
x86_64). The remaining dict-decode gap is the entropy / sequence-decode work
(FSE table build + the per-sequence decode-and-execute loop + the ext-dict
copy), a separate deeper track.

Hoist the dict-walk reachability floor out of the lazy chain loop

The lazy hash-chain dict-match walk recomputed the candidate offset
(current_idx - dict_idx) every iteration solely to gate on decoder
reachability (offset <= max_window_size). The offset is only consumed when a
candidate wins, which is rare on the walk. Hoist the equivalent floor
(current_idx.saturating_sub(max_window_size)) once before the loop and gate on
dict_idx >= floor; the per-iteration subtract moves to the rare win branch and
the max_window_size register is freed inside the hot loop (it matters on the
register-starved 32-bit path). Mirrors C's ZSTD_HcFindBestMatch dms loop,
which bounds reachability by chain construction rather than re-checking each
candidate.

dict_idx >= current_idx - max_window_size is algebraically the same gate as
current_idx - dict_idx <= max_window_size given dict_idx < current_idx (dict
positions precede the cursor), so it is byte-identical.

Leading scalar word probe in the SIMD common-prefix kernels

The SIMD common_prefix_len_ptr (avx2 / sse42 / neon / simd128) ran the wide
vector loop even when the prefix diverges within the first 8 bytes. The
optimal parser calls the seeded prefix counter on every visited BT-tree node,
and each node extends the running seed by only a short run before the
smaller/larger split, so that divergence is almost always inside the first
word and the vector load + compare is pure overhead. Upstream C ZSTD_count
leads with one MEM_readST (8-byte) check and returns on a mismatch there;
mirror it with a leading scalar word probe, falling through to the vector loop
only when the first word matches (long matches). The scalar fallback kernel is
already word-at-a-time and is unchanged.

Same-host ours-vs-c_ffi (flat control arm), both arches:

Workload i686 x86_64
compress-dict/level_13_lazy/small-10k-random −7.2 % −5.1 %
compress/level_19_btultra2/large-log-stream −7.7 % −5.0 %

The long-match (large-log-stream) path benefits too, since per-node tree
extensions stay short regardless of total match length. Byte-identical.

Testing

  • cargo nextest run -p structured-zstd --features hash,std,dict_builder — 838 pass
  • cargo nextest run -p ffi-bench --features bench_internals,dict_builder — 59 pass
    (dict cross-validation: rust-compress/ffi-decompress + ffi-compress/rust-decompress + fuzz_interop)
  • cargo clippy (default + no-std + --tests) clean; cargo fmt --check clean
  • i9 (x86_64) + i686 same-host ours-vs-c_ffi A/B with a flat control arm

Summary by CodeRabbit

  • Performance Improvements

    • Faster prefix matching in several optimized paths, especially when differences occur near the start of data.
    • Reduced overhead during dictionary-based matching for compression, improving hot-path efficiency.
  • Bug Fixes

    • Improved frame decoding from in-memory data when using dictionaries, with more direct header handling and consistent dictionary checks.

polaz added 3 commits June 30, 2026 00:39
decode_all_with_dict_handle still routed its per-frame header read through
the Read-trait reset_with_dict_handle (per-field read_exact via the io::impls
shim) while the non-dict decode_all already parsed the header straight from
the input slice. Add reset_from_slice_with_dict_handle, mirroring the
Read-based dict reset but reading the header via read_frame_header_from_slice
and applying it through the shared parsed-header path, then attaching the
dictionary. Wire decode_all_with_dict_handle through it.

Byte-identical (dict cross-validation + fuzz_interop round-trips pass).
The lazy hash-chain dict-match walk recomputed the candidate offset
(current_idx - dict_idx) every iteration solely to gate on decoder
reachability (offset <= max_window_size). The offset is only consumed when a
candidate WINS, which is rare on the walk. Hoist the equivalent floor
(current_idx.saturating_sub(max_window_size)) once before the loop and gate on
dict_idx >= floor; the per-iteration subtract moves to the (rare) win branch and
the max_window_size register is freed inside the hot loop. Mirrors C's
ZSTD_HcFindBestMatch dms loop, which bounds reachability by chain construction
rather than re-checking each candidate.

Byte-identical: dict_idx >= current_idx - max_window_size is algebraically the
same gate as current_idx - dict_idx <= max_window_size given dict_idx <
current_idx (dict positions precede the cursor). Dict cross-validation +
fuzz_interop round-trips pass.
…ernels

The SIMD common_prefix_len_ptr (avx2 / sse42 / neon / simd128) ran the wide
vector loop even when the prefix diverges within the first 8 bytes. On BT-tree
node compares — the optimal parser calls the seeded prefix counter per visited
node, and each node extends the running seed by only a short run before the
smaller/larger split — that divergence is almost always inside the first word,
so the vector load + compare is pure overhead. Upstream C ZSTD_count leads with
one MEM_readST (8-byte) check and returns on a mismatch there; mirror it with a
leading scalar word probe, falling through to the vector loop only when the
first word matches (long matches).

i686 (ours-vs-c_ffi, flat control): compress-dict L13 small-10k-random
782->725us (-7.2%); compress L19 btultra2 large-log-stream 64.5->59.5ms
(-7.7%) — the long-match path benefits too, since per-node tree extensions are
short regardless of total match length. Byte-identical (838 lib + 59 ffi incl
cross-validation; scalar already word-at-a-time). The scalar fallback kernel is
unchanged.
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bacda8c0-ab5f-413b-ae46-2946668065c4

📥 Commits

Reviewing files that changed from the base of the PR and between 7b005e4 and 1aa1aab.

📒 Files selected for processing (6)
  • zstd/src/decoding/frame_decoder.rs
  • zstd/src/encoding/fastpath/avx2_bmi2.rs
  • zstd/src/encoding/fastpath/neon.rs
  • zstd/src/encoding/fastpath/simd128.rs
  • zstd/src/encoding/fastpath/sse42.rs
  • zstd/src/encoding/hc/mod.rs

📝 Walkthrough

Walkthrough

Adds FrameDecoder::reset_from_slice_with_dict_handle for slice-direct frame header parsing with dictionary validation, and switches decode_all_with_dict_handle to use it. Four SIMD common_prefix_len_ptr implementations gain a leading scalar usize mismatch probe. dms_chain_walk hoists the dict reachability threshold out of its hot loop.

Changes

FrameDecoder slice-based dict-handle reset

Layer / File(s) Summary
reset_from_slice_with_dict_handle + wiring
zstd/src/decoding/frame_decoder.rs
New pub(crate) method parses frame header from slice, validates lsm pinned expectations, checks dictionary_id, and installs dict into decoder_scratch/active_dict/using_dict. decode_all_with_dict_handle is updated to call it instead of init_with_dict_handle in both lsm and non-lsm branches.

Encoder fastpath and HC loop optimizations

Layer / File(s) Summary
Leading scalar usize probe in SIMD common_prefix_len_ptr
zstd/src/encoding/fastpath/avx2_bmi2.rs, zstd/src/encoding/fastpath/neon.rs, zstd/src/encoding/fastpath/simd128.rs, zstd/src/encoding/fastpath/sse42.rs
Each architecture-specific implementation gains an early return that unaligned-reads the first usize from both pointers, XORs, and returns scalar::mismatch_byte_index immediately on difference, before entering the SIMD vector scan.
Hoisted reachability threshold in dms_chain_walk
zstd/src/encoding/hc/mod.rs
Precomputes dict_reachable_floor = current_idx.saturating_sub(max_window_size) outside the loop; per-iteration check becomes dict_idx >= dict_reachable_floor instead of computing new_offset each iteration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇 A rabbit hops through bytes so fast,
With scalar probes that make SIMD last—
The dict-id checked, the slice parsed clean,
The loop's hot floor pre-fetched and lean.
No extra math in every spin,
Just clever bounds to let us win! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the three main performance changes in the PR and is specific enough for history scanning.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/dict-band-hotpath

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.27451% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
zstd/src/decoding/frame_decoder.rs 80.64% 6 Missing ⚠️
zstd/src/encoding/fastpath/sse42.rs 88.88% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown

Greptile Summary

This PR speeds up dictionary decode and match-prefix hot paths. The main changes are:

  • Adds slice-direct frame-header parsing for dictionary-handle decode.
  • Adds leading scalar word probes before SIMD prefix loops.
  • Hoists the dictionary match reachability floor out of the HC chain walk.

Confidence Score: 5/5

The optimized hot-path changes appear merge-safe with no review comments to address.

The changes are narrowly scoped performance improvements, preserve byte-identical behavior by construction, and are supported by the reported codec, interop, clippy, formatting, and benchmark validation.

T-Rex T-Rex Logs

What T-Rex did

  • Copied the dict-decode-slice-header test harness into the zstd/src directory for use in both runs.
  • Ran the dict-decode-slice-header test on the base commit and verified an exit code of 0 with a byte-identical decode and the expected wrong-dictionary error.
  • Ran the dict-decode-slice-header test on the head commit and verified an exit code of 0 with the same decode and the same wrong-dictionary error.
  • Appended the dict-walk-floor Rust test harness to zstd/src/tests/dict_test.rs for use in each attempted run.
  • Tried the base run of the dict-walk-floor test and observed an exit code of 127 with cargo: command not found.
  • Tried the head run of the dict-walk-floor test and observed an exit code of 127 with cargo: command not found.
  • Captured an environment log showing cargo is absent from standard install locations.
  • Generated the simd-prefix-word-probe harness that would exercise the SIMD prefix matrix and a deterministic compression hash.
  • Captured the before-state log for the simd-prefix-word-probe, including the exact base checkout/test command, cwd, failure output, and exit code 127.
  • Captured the after-state log for the simd-prefix-word-probe, including the head checkout/test command, cwd, failure output, and exit code 127.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "perf(compress): leading scalar word prob..." | Re-trigger Greptile

@polaz polaz merged commit e29b9e7 into main Jun 30, 2026
28 checks passed
@polaz polaz deleted the perf/dict-band-hotpath branch June 30, 2026 08:13
@sw-release-bot sw-release-bot Bot mentioned this pull request Jun 30, 2026
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