Skip to content

perf(encoding): CRC-gated hash mix for ARM and x86_64#102

Merged
polaz merged 9 commits intomainfrom
perf/#71-crc-hash-gating
Apr 11, 2026
Merged

perf(encoding): CRC-gated hash mix for ARM and x86_64#102
polaz merged 9 commits intomainfrom
perf/#71-crc-hash-gating

Conversation

@polaz
Copy link
Copy Markdown
Member

@polaz polaz commented Apr 11, 2026

Summary

  • add runtime-gated AArch64 CRC hash-mix path in encoding matcher hot path
  • add runtime-gated x86_64 SSE4.2 CRC32 hash-mix path with scalar fallback
  • hoist hash-mix kernel selection out of the per-hash hot path into one-time cached dispatch
  • reuse shared hash-mix in dfast and row hash indexing
  • add CPU-gated tests that validate accelerated-path equivalence (not only determinism)
  • update issue perf: ARM platform optimizations (CRC32 hash, NEON copy, SVE2 histcnt) #71 scope to include SSE4.2 CRC32 and CPU-gated test expectations

Validation

  • cargo clippy --all-targets -- -D warnings
  • cargo nextest run -p structured-zstd (311/311 passed)
  • cargo llvm-cov -p structured-zstd --lcov --output-path /tmp/structured-zstd.lcov (local diff lines covered)
  • cargo bench --bench compare_ffi -p structured-zstd --features dict_builder -- compress/default/high-entropy-1m/matrix --nocapture

Part of #71

Summary by CodeRabbit

  • Performance

    • Added a selectable 64-bit hash-mixing layer with platform-accelerated kernels and a safe scalar fallback; match indexing now uses this for more consistent, faster behavior with runtime selection.
  • Tests

    • Expanded tests to validate accelerated and scalar paths across architectures and ensure accelerated implementations match expected results, improving deterministic validation.

Copilot AI review requested due to automatic review settings April 11, 2026 10:08
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cd85d2ee-afff-41a8-8d90-dbe7041e9e18

📥 Commits

Reviewing files that changed from the base of the PR and between 46927db and 33b482f.

📒 Files selected for processing (1)
  • zstd/src/encoding/match_generator.rs

📝 Walkthrough

Walkthrough

Introduces a runtime-selectable 64-bit hash-mixing abstraction used by match generators: adds HashMixKernel, hash_mix_u64_with_kernel(...), CPU-feature detection/selection, and replaces multiplicative-prime hashing in DfastMatchGenerator and RowMatchGenerator; includes feature-gated tests for accelerated and scalar paths.

Changes

Cohort / File(s) Summary
Hash mix kernel & detection
zstd/src/encoding/match_generator.rs
Add HashMixKernel enum, hash_mix_u64_with_kernel(value, kernel), architecture-accelerated kernels (x86_64 SSE4.2, aarch64 CRC), scalar fallback, and detect_hash_mix_kernel() with optional cached selection under std.
Match generator integration
zstd/src/encoding/match_generator.rs
Store selected kernel on DfastMatchGenerator and RowMatchGenerator; replace prior multiplicative-prime hashing with hash_mix_u64_with_kernel(...); update HcMatchGenerator::hash_position to use shared prime constant.
Tests & verification
zstd/src/encoding/match_generator.rs (tests)
Update row/tag extraction test to validate new hash-mix bit-splitting contract; add std-gated tests asserting accelerated kernels match their intrinsic implementations and scalar kernel correctness; add helpers to force kernel selection in tests.

Sequence Diagram(s)

sequenceDiagram
    participant Generator as "MatchGenerator"
    participant Selector as "HashMixKernel selector"
    participant Impl as "hash_mix_u64 implementation"
    rect rgba(30,144,255,0.5)
      Generator->>Selector: request kernel (init / first use)
      Selector->>Selector: detect CPU features / read cached value
      Selector-->>Generator: return kernel
    end
    rect rgba(34,139,34,0.5)
      Generator->>Impl: call hash_mix_u64_with_kernel(value, kernel)
      alt Kernel == SSE4.2
        Impl->>Impl: use `_mm_crc32_u64` + mix
      else Kernel == AArch64 CRC
        Impl->>Impl: use `__crc32d` + mix
      else
        Impl->>Impl: scalar multiplicative fallback
      end
      Impl-->>Generator: return mixed 64-bit hash
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Poem

🐇 I hopped through bits and mixed them fine,
CRC, primes, each tiny line,
Kernel picked by sniff and test,
Rows tag-split and do their best,
A rabbit cheered — the hashes shine.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the main change: adding CRC-based hash mixing for ARM (aarch64) and x86_64 architectures with runtime gating.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/#71-crc-hash-gating

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

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a shared hash_mix_u64 helper used by encoding matchers, with runtime CPU-feature–gated CRC32-based mixing on AArch64 (crc) and x86_64 (SSE4.2), plus scalar fallback, to reduce hash-mix cost in hot paths while keeping portability.

Changes:

  • Introduces hash_mix_u64 with CRC32-based mix paths for AArch64 and x86_64 (runtime-gated under std, compile-time-gated under no_std).
  • Switches dfast and row matchers to use the shared hash-mix contract instead of per-site multiplicative hashing.
  • Adds CPU-gated tests intended to validate determinism/availability of the CRC hash paths.

Comment thread zstd/src/encoding/match_generator.rs Outdated
Comment thread zstd/src/encoding/match_generator.rs Outdated
Comment thread zstd/src/encoding/match_generator.rs Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@zstd/src/encoding/match_generator.rs`:
- Around line 102-145: Remove the unnecessary `return` keywords in the
feature-probe helpers and drop redundant casts of the CRC intrinsics: in
sse42_crc_hash_available() remove the explicit `return` and use the expression
value from HAS_SSE42.get_or_init(...); in crc_hash_available() do the same; in
hash_mix_u64_sse42() remove the cast on the result of _mm_crc32_u64 (it already
yields the correct integer type) before shifting/xoring; likewise remove any
redundant cast on __crc32d in hash_mix_u64_crc() if present. Update the
functions sse42_crc_hash_available, crc_hash_available, hash_mix_u64_sse42, and
hash_mix_u64_crc accordingly to satisfy clippy.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5939ac12-c4fb-4eeb-986b-88ce23a92d03

📥 Commits

Reviewing files that changed from the base of the PR and between 8cef003 and 4e09e87.

📒 Files selected for processing (1)
  • zstd/src/encoding/match_generator.rs

Comment thread zstd/src/encoding/match_generator.rs Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 11, 2026

Codecov Report

❌ Patch coverage is 91.89189% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
zstd/src/encoding/match_generator.rs 91.89% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@zstd/src/encoding/match_generator.rs`:
- Around line 4299-4323: The tests only check hash_mix_u64 is deterministic, not
that the accelerated path is selected; update each guarded test (the ones using
is_x86_feature_detected!("sse4.2") and is_aarch64_feature_detected!("crc")) to
invoke the architecture-specific implementation directly and compare it to
hash_mix_u64 so the accelerated path is exercised and verified (i.e., call the
SSE/CRC helper used by hash_mix_u64 under the same runtime guard and assert
equality between that helper and hash_mix_u64 for the test vector).
- Around line 79-98: hash_mix_u64 currently checks
sse42_crc_hash_available()/crc_hash_available() on every call, which hurts
hot-path performance in DfastMatchGenerator::hash_index and
RowMatchGenerator::hash_and_row; instead, determine the mixer once at startup or
first use and dispatch directly. Replace the per-call branching in hash_mix_u64
with a thin dispatcher that calls a preselected function (e.g., a static
OnceLock or lazy-initialized function pointer/enum) which is set to either
hash_mix_u64_sse42, hash_mix_u64_crc, or the scalar multiplier, and ensure the
unsafe SSE4.2/CRC variants are only invoked when the corresponding feature
detection has run and selected them (preserve the SAFETY guards). Update callers
(DfastMatchGenerator::hash_index, RowMatchGenerator::hash_and_row) to call the
new dispatcher (or keep calling hash_mix_u64 if it becomes the cheap indirect
call) so the hot path no longer performs per-hash feature checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3faf388a-2c9f-497d-a893-a19acfcc6a1f

📥 Commits

Reviewing files that changed from the base of the PR and between 4e09e87 and 574bb57.

📒 Files selected for processing (1)
  • zstd/src/encoding/match_generator.rs

Comment thread zstd/src/encoding/match_generator.rs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@zstd/src/encoding/match_generator.rs`:
- Around line 193-199: with_forced_hash_mix_kernel currently unsafely mutates
global HASH_MIX_KERNEL without synchronization and fails to restore on panic;
change it to acquire the HASH_MIX_KERNEL_TEST_LOCK (serialize with other tests)
and set HASH_MIX_KERNEL inside a guard object that restores the previous value
in Drop so restoration happens even if f() panics (i.e., make
with_forced_hash_mix_kernel take the lock, swap kernel, run f(), and rely on a
RAII restore-on-drop guard to reset HASH_MIX_KERNEL). Also update
accelerated-path tests to acquire the same HASH_MIX_KERNEL_TEST_LOCK before
calling hash_mix_u64(...) so they cannot race with forced-kernel tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 69135b0f-650a-48b6-bdf9-33e48c065723

📥 Commits

Reviewing files that changed from the base of the PR and between 04eb072 and 7737c5f.

📒 Files selected for processing (1)
  • zstd/src/encoding/match_generator.rs

Comment thread zstd/src/encoding/match_generator.rs Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread zstd/src/encoding/match_generator.rs Outdated
polaz added 6 commits April 11, 2026 14:03
- add aarch64 crc-enabled hash mixing path with runtime/static feature detection

- keep multiplicative fallback for non-crc and non-arm targets

- apply shared hash mix in dfast and row hash indexing

- align row hash test with shared hash-mix contract
- extend hash mix with runtime-gated SSE4.2 CRC32 on x86_64

- keep scalar fallback and existing aarch64 CRC path

- add CPU-gated determinism tests for crc hash paths
- remove needless returns in feature-detection helpers

- drop redundant u64 cast in sse4.2 crc mix path
@polaz polaz force-pushed the perf/#71-crc-hash-gating branch from 7737c5f to c4ea535 Compare April 11, 2026 11:05
@polaz polaz requested a review from Copilot April 11, 2026 11:12
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
zstd/src/encoding/match_generator.rs (1)

4311-4340: ⚠️ Potential issue | 🟡 Minor

Serialize this row hash test against the forced-kernel coverage tests.

Line 4324 and Line 4331 both depend on hash_mix_u64, but this test does not hold HASH_MIX_KERNEL_TEST_LOCK. If it runs in parallel with the forced-scalar coverage on Lines 4383-4411, the first call can see one kernel and the second another, making the row/tag assertion flaky.

🛠️ Suggested fix
 fn row_hash_and_row_extracts_high_bits() {
+    #[cfg(feature = "std")]
+    let _lock = HASH_MIX_KERNEL_TEST_LOCK
+        .lock()
+        .expect("hash mix test lock poisoned");
+
     let mut matcher = RowMatchGenerator::new(1 << 22);
     matcher.configure(ROW_CONFIG);
     matcher.add_data(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@zstd/src/encoding/match_generator.rs` around lines 4311 - 4340, The test
row_hash_and_row_extracts_high_bits calls hash_mix_u64 twice without holding the
global HASH_MIX_KERNEL_TEST_LOCK, causing flaky behavior when kernel selection
is raced by other coverage tests; fix by acquiring HASH_MIX_KERNEL_TEST_LOCK at
the start of row_hash_and_row_extracts_high_bits (e.g., call
HASH_MIX_KERNEL_TEST_LOCK.lock() and hold the guard for the duration of the
test) before any hash_mix_u64 calls and let the guard drop at the end so both
hash_mix_u64 invocations see the same kernel selection.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@zstd/src/encoding/match_generator.rs`:
- Around line 4311-4340: The test row_hash_and_row_extracts_high_bits calls
hash_mix_u64 twice without holding the global HASH_MIX_KERNEL_TEST_LOCK, causing
flaky behavior when kernel selection is raced by other coverage tests; fix by
acquiring HASH_MIX_KERNEL_TEST_LOCK at the start of
row_hash_and_row_extracts_high_bits (e.g., call HASH_MIX_KERNEL_TEST_LOCK.lock()
and hold the guard for the duration of the test) before any hash_mix_u64 calls
and let the guard drop at the end so both hash_mix_u64 invocations see the same
kernel selection.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 174b7518-49cc-4f15-897e-178709d312f3

📥 Commits

Reviewing files that changed from the base of the PR and between 7737c5f and c4ea535.

📒 Files selected for processing (1)
  • zstd/src/encoding/match_generator.rs

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@polaz polaz requested a review from Copilot April 11, 2026 11:31
@polaz
Copy link
Copy Markdown
Member Author

polaz commented Apr 11, 2026

@coderabbitai Duplicate body item about \ lock is fixed in commit 904d2b0: the test now acquires \ before any \ call to avoid cross-test kernel races.

@polaz
Copy link
Copy Markdown
Member Author

polaz commented Apr 11, 2026

@coderabbitai Duplicate body item about row_hash_and_row_extracts_high_bits lock is fixed in commit 904d2b0: the test now acquires HASH_MIX_KERNEL_TEST_LOCK before any hash_mix_u64 call to avoid cross-test kernel races.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

Tip

For best results, initiate chat on the files or code changes.

@polaz: Thanks for the confirmation! Acquiring the lock before any with_forced_hash_mix_kernel call is the right approach — it ensures the global HASH_MIX_KERNEL atomic is not mutated by another test thread between the with_forced_hash_mix_kernel setup and the assertion, eliminating the potential race window entirely.


✏️ Learnings added
Learnt from: polaz
URL: https://github.com/structured-world/structured-zstd/pull/102

Timestamp: 2026-04-11T11:31:46.064Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#102`), the test-only `with_forced_hash_mix_kernel(...)` helper forces the global `HASH_MIX_KERNEL` atomic to a specific kernel for coverage. Tests that call this helper must acquire a shared mutex lock *before* the `with_forced_hash_mix_kernel` call (not only around the assertion) to prevent cross-test kernel races when `cargo nextest` runs tests in parallel. This pattern was locked in commit 904d2b0. Do not flag the lock acquisition as unnecessarily early.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/frame_compressor.rs:779-805
Timestamp: 2026-04-11T07:48:58.281Z
Learning: In `zstd/src/encoding/frame_compressor.rs` (structured-world/structured-zstd, PR `#99`), a temporary compatibility guard exists for sub-256-byte compressed payloads: the 1-byte-FCS single-segment form is not yet fully C-FFI compatible for payloads below 256 bytes, and a compat guard was added to handle this case while the path is hardened. Do not flag this guard as unnecessary.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T21:51:51.926Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test suite for `copy_bytes_overshooting` includes a misaligned extra-capacity case that exercises the rounded-up wildcopy path (where `copy_multiple > copy_at_least`) and validates prefix correctness for that scenario. Do not flag the absence of a misaligned/overshooting extra-capacity sub-case as missing test coverage.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/streaming_encoder.rs:252-255
Timestamp: 2026-04-11T09:21:04.781Z
Learning: In `zstd/src/encoding/streaming_encoder.rs` (structured-world/structured-zstd, PR `#99`), the `single_segment` gate in `ensure_frame_started` intentionally includes the `size <= window_size` condition alongside the `(512..=(1<<14)).contains(&size)` range check. This mirrors the zstd C donor invariant `singleSegment = contentSizeFlag && windowSize >= pledgedSrcSize` from `zstd_compress.c` — single-segment is only valid when the matcher window can cover the full pledged payload. The regression test `single_segment_requires_pledged_to_fit_matcher_window` locks this behavior. Do not suggest removing `size <= window_size` from the single-segment gate.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 58
File: .github/workflows/ci.yml:31-32
Timestamp: 2026-04-03T11:24:17.021Z
Learning: In `structured-world/structured-zstd`, the CI Clippy lint job (`.github/workflows/ci.yml`) uses two separate steps: (1) the required gate: `cargo clippy -p structured-zstd --features hash,std,dict_builder -- -D warnings`, and (2) a separate bench-internals step: `cargo clippy -p structured-zstd --features hash,std,dict_builder,bench_internals -- -D warnings`. The `bench_internals` feature must NOT replace the primary gate — it runs as an additional step only.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-11T07:15:56.578Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#99`), `RowMatchGenerator::skip_matching_with_hint(Some(true))` performs sparse-prefix insertion via `insert_positions_with_step(current_abs_start, current_abs_end, INCOMPRESSIBLE_SKIP_STEP)` followed by a dense-tail reseed over `ROW_MIN_MATCH_LEN + INCOMPRESSIBLE_SKIP_STEP` positions, skipping sparse-grid positions (`!(pos - current_abs_start).is_multiple_of(INCOMPRESSIBLE_SKIP_STEP)`). The `MatcherBackend::Row` dispatch in `MatchGeneratorDriver::skip_matching_with_hint` now passes the hint through to the Row backend. A regression test `row_skip_matching_with_incompressible_hint_uses_sparse_prefix` covers this. Do not flag Row as ignoring incompressible hints or defaulting to dense-only skip.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/match_generator.rs:1675-1701
Timestamp: 2026-04-10T07:20:51.122Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd), `DfastMatchGenerator::skip_matching` (the dense/non-sparse path, i.e. when `used_sparse` is false) backfills the previous-slice tail (`current_abs_start.saturating_sub(DFAST_MIN_MATCH_LEN + 3) .. current_abs_start`) before calling `insert_positions(current_abs_start, current_abs_end)`. This mirrors the `skip_matching_dense` backfill and `HcMatchGenerator::backfill_boundary_positions` patterns, ensuring positions at block boundaries become hashable as soon as the next slice extends history. A regression test `dfast_dense_skip_matching_backfills_previous_tail_for_next_block` covers immediate cross-boundary matching after a dense skip. Do not flag the absence of this backfill as a missing step.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-06T01:40:24.378Z
Learning: In `zstd/benches/compare_ffi.rs` (structured-world/structured-zstd), Rust FastCOVER trains with the post-finalization content budget in both the `REPORT_DICT_TRAIN` emission path (around lines 208-225) and the Criterion benchmark path (around lines 266-280). Both paths were aligned in commit 8622344. Do not flag these ranges as using inconsistent budget values.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T16:00:30.438Z
Learning: In `zstd/src/encoding/match_generator.rs`, the `RowMatchGenerator` (used for `CompressionLevel::Level(4)` / `MatcherBackend::Row`) uses a stable 4-byte hash key, consistent with the 4-byte lookahead constraint shared by `HcMatchGenerator`. Previous-block tail positions are backfilled into the row tables before matching/skip begins (analogous to `backfill_boundary_positions` for the HC backend), and a regression test covers cross-boundary tail reuse. Do not flag missing backfill or key-width issues for the Row backend.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T21:51:56.626Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test `copy_bytes_overshooting_preserves_prefix_for_runtime_chunk_lengths` (or equivalent) includes a misaligned extra-capacity case that uses `add(1)`-offset pointers and a `chunk_plus_one` length to exercise the rounded-up wildcopy overshoot path (where `copy_multiple > copy_at_least`) and validates prefix correctness. Do not flag the absence of a misaligned-pointer case in this test — it is present by design.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T20:26:15.902Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test `copy_bytes_overshooting_covers_all_copy_strategies` derives copy lengths from a helper `active_chunk_size_for_tests()` (not hardcoded values) so that single-chunk, multi-chunk, and sub-chunk (fallback) cases adapt to whichever SIMD backend width is active at runtime (AVX-512/AVX2/SSE2/NEON/scalar). Do not flag hardcoded test lengths as missing coverage for other backends — the test is backend-adaptive by design.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

Tip

For best results, initiate chat on the files or code changes.

@polaz: Thanks for confirming — acquiring HASH_MIX_KERNEL_TEST_LOCK before any hash_mix_u64 call in row_hash_and_row_extracts_high_bits is the correct fix to prevent cross-test kernel state races.


✏️ Learnings added
Learnt from: polaz
URL: https://github.com/structured-world/structured-zstd/pull/102

Timestamp: 2026-04-11T11:31:54.265Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#102`), the test `row_hash_and_row_extracts_high_bits` acquires `HASH_MIX_KERNEL_TEST_LOCK` before any `hash_mix_u64` call (fixed in commit 904d2b0). This lock guards all tests that force a specific `HashMixKernel` via `with_forced_hash_mix_kernel(...)` to prevent cross-test kernel races caused by the global `HASH_MIX_KERNEL` atomic. Do not flag the absence of this lock as missing — it is acquired at the top of each affected test.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T16:00:30.438Z
Learning: In `zstd/src/encoding/match_generator.rs`, the `RowMatchGenerator` (used for `CompressionLevel::Level(4)` / `MatcherBackend::Row`) uses a stable 4-byte hash key, consistent with the 4-byte lookahead constraint shared by `HcMatchGenerator`. Previous-block tail positions are backfilled into the row tables before matching/skip begins (analogous to `backfill_boundary_positions` for the HC backend), and a regression test covers cross-boundary tail reuse. Do not flag missing backfill or key-width issues for the Row backend.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/frame_compressor.rs:779-805
Timestamp: 2026-04-11T07:48:58.281Z
Learning: In `zstd/src/encoding/frame_compressor.rs` (structured-world/structured-zstd, PR `#99`), a temporary compatibility guard exists for sub-256-byte compressed payloads: the 1-byte-FCS single-segment form is not yet fully C-FFI compatible for payloads below 256 bytes, and a compat guard was added to handle this case while the path is hardened. Do not flag this guard as unnecessary.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/streaming_encoder.rs:252-255
Timestamp: 2026-04-11T09:21:04.781Z
Learning: In `zstd/src/encoding/streaming_encoder.rs` (structured-world/structured-zstd, PR `#99`), the `single_segment` gate in `ensure_frame_started` intentionally includes the `size <= window_size` condition alongside the `(512..=(1<<14)).contains(&size)` range check. This mirrors the zstd C donor invariant `singleSegment = contentSizeFlag && windowSize >= pledgedSrcSize` from `zstd_compress.c` — single-segment is only valid when the matcher window can cover the full pledged payload. The regression test `single_segment_requires_pledged_to_fit_matcher_window` locks this behavior. Do not suggest removing `size <= window_size` from the single-segment gate.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T21:51:51.926Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test suite for `copy_bytes_overshooting` includes a misaligned extra-capacity case that exercises the rounded-up wildcopy path (where `copy_multiple > copy_at_least`) and validates prefix correctness for that scenario. Do not flag the absence of a misaligned/overshooting extra-capacity sub-case as missing test coverage.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 58
File: .github/workflows/ci.yml:31-32
Timestamp: 2026-04-03T11:24:17.021Z
Learning: In `structured-world/structured-zstd`, the CI Clippy lint job (`.github/workflows/ci.yml`) uses two separate steps: (1) the required gate: `cargo clippy -p structured-zstd --features hash,std,dict_builder -- -D warnings`, and (2) a separate bench-internals step: `cargo clippy -p structured-zstd --features hash,std,dict_builder,bench_internals -- -D warnings`. The `bench_internals` feature must NOT replace the primary gate — it runs as an additional step only.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-11T07:15:56.578Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#99`), `RowMatchGenerator::skip_matching_with_hint(Some(true))` performs sparse-prefix insertion via `insert_positions_with_step(current_abs_start, current_abs_end, INCOMPRESSIBLE_SKIP_STEP)` followed by a dense-tail reseed over `ROW_MIN_MATCH_LEN + INCOMPRESSIBLE_SKIP_STEP` positions, skipping sparse-grid positions (`!(pos - current_abs_start).is_multiple_of(INCOMPRESSIBLE_SKIP_STEP)`). The `MatcherBackend::Row` dispatch in `MatchGeneratorDriver::skip_matching_with_hint` now passes the hint through to the Row backend. A regression test `row_skip_matching_with_incompressible_hint_uses_sparse_prefix` covers this. Do not flag Row as ignoring incompressible hints or defaulting to dense-only skip.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/match_generator.rs:1675-1701
Timestamp: 2026-04-10T07:20:51.122Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd), `DfastMatchGenerator::skip_matching` (the dense/non-sparse path, i.e. when `used_sparse` is false) backfills the previous-slice tail (`current_abs_start.saturating_sub(DFAST_MIN_MATCH_LEN + 3) .. current_abs_start`) before calling `insert_positions(current_abs_start, current_abs_end)`. This mirrors the `skip_matching_dense` backfill and `HcMatchGenerator::backfill_boundary_positions` patterns, ensuring positions at block boundaries become hashable as soon as the next slice extends history. A regression test `dfast_dense_skip_matching_backfills_previous_tail_for_next_block` covers immediate cross-boundary matching after a dense skip. Do not flag the absence of this backfill as a missing step.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-06T01:40:24.378Z
Learning: In `zstd/benches/compare_ffi.rs` (structured-world/structured-zstd), Rust FastCOVER trains with the post-finalization content budget in both the `REPORT_DICT_TRAIN` emission path (around lines 208-225) and the Criterion benchmark path (around lines 266-280). Both paths were aligned in commit 8622344. Do not flag these ranges as using inconsistent budget values.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T21:51:56.626Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test `copy_bytes_overshooting_preserves_prefix_for_runtime_chunk_lengths` (or equivalent) includes a misaligned extra-capacity case that uses `add(1)`-offset pointers and a `chunk_plus_one` length to exercise the rounded-up wildcopy overshoot path (where `copy_multiple > copy_at_least`) and validates prefix correctness. Do not flag the absence of a misaligned-pointer case in this test — it is present by design.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T20:26:15.902Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test `copy_bytes_overshooting_covers_all_copy_strategies` derives copy lengths from a helper `active_chunk_size_for_tests()` (not hardcoded values) so that single-chunk, multi-chunk, and sub-chunk (fallback) cases adapt to whichever SIMD backend width is active at runtime (AVX-512/AVX2/SSE2/NEON/scalar). Do not flag hardcoded test lengths as missing coverage for other backends — the test is backend-adaptive by design.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread zstd/src/encoding/match_generator.rs Outdated
@polaz
Copy link
Copy Markdown
Member Author

polaz commented Apr 11, 2026

@coderabbitai Copilot outdated thread PRRT_kwDORv-2jM56S4K5 is now stale after 46927db: hash kernel dispatch moved into matcher state (hash_mix_kernel field in Dfast/Row), so hot-path hashing no longer uses atomic load + global branch.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@polaz: Understood — after commit 46927db, the global-atomic hot-path dispatch is gone. The hash_mix_kernel field is now stored directly in the DfastMatchGenerator and RowMatchGenerator structs, so kernel selection is resolved once (at construction/initialisation) and the per-hash call reduces to a plain field read with no atomic overhead. I'll resolve thread PRRT_kwDORv-2jM56S4K5 and record the updated architecture.


🏁 Script executed:

#!/bin/bash
# Resolve the stale review thread
gh api graphql -f query='
mutation {
  resolveReviewThread(input: { threadId: "PRRT_kwDORv-2jM56S4K5" }) {
    thread {
      id
      isResolved
    }
  }
}'

Length of output: 92


@polaz: Thread PRRT_kwDORv-2jM56S4K5 is now resolved. The learning has been recorded — future reviews will recognise that the hot-path hash dispatch in DfastMatchGenerator and RowMatchGenerator is a plain struct-field read after commit 46927db, not a per-call atomic load.


✏️ Learnings added
Learnt from: polaz
URL: https://github.com/structured-world/structured-zstd/pull/102

Timestamp: 2026-04-11T11:56:17.795Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#102`), after commit 46927db, hash-mix kernel dispatch was moved from the global `HASH_MIX_KERNEL` AtomicU8 hot-path read into a per-matcher instance field `hash_mix_kernel` stored directly in `DfastMatchGenerator` and `RowMatchGenerator`. The hot path no longer performs an atomic load or global branch; kernel selection happens once at matcher initialisation and is subsequently a plain struct-field read. Do not flag the hot path as doing a per-call atomic load — that pattern was superseded by commit 46927db.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-11T11:31:54.265Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#102`), the test `row_hash_and_row_extracts_high_bits` acquires `HASH_MIX_KERNEL_TEST_LOCK` before any `hash_mix_u64` call (fixed in commit 904d2b0). This lock guards all tests that force a specific `HashMixKernel` via `with_forced_hash_mix_kernel(...)` to prevent cross-test kernel races caused by the global `HASH_MIX_KERNEL` atomic. Do not flag the absence of this lock as missing — it is acquired at the top of each affected test.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-11T11:31:46.064Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#102`), the test-only `with_forced_hash_mix_kernel(...)` helper forces the global `HASH_MIX_KERNEL` atomic to a specific kernel for coverage. Tests that call this helper must acquire a shared mutex lock *before* the `with_forced_hash_mix_kernel` call (not only around the assertion) to prevent cross-test kernel races when `cargo nextest` runs tests in parallel. This pattern was locked in commit 904d2b0. Do not flag the lock acquisition as unnecessarily early.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T16:00:30.438Z
Learning: In `zstd/src/encoding/match_generator.rs`, the `RowMatchGenerator` (used for `CompressionLevel::Level(4)` / `MatcherBackend::Row`) uses a stable 4-byte hash key, consistent with the 4-byte lookahead constraint shared by `HcMatchGenerator`. Previous-block tail positions are backfilled into the row tables before matching/skip begins (analogous to `backfill_boundary_positions` for the HC backend), and a regression test covers cross-boundary tail reuse. Do not flag missing backfill or key-width issues for the Row backend.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-11T07:15:56.578Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#99`), `RowMatchGenerator::skip_matching_with_hint(Some(true))` performs sparse-prefix insertion via `insert_positions_with_step(current_abs_start, current_abs_end, INCOMPRESSIBLE_SKIP_STEP)` followed by a dense-tail reseed over `ROW_MIN_MATCH_LEN + INCOMPRESSIBLE_SKIP_STEP` positions, skipping sparse-grid positions (`!(pos - current_abs_start).is_multiple_of(INCOMPRESSIBLE_SKIP_STEP)`). The `MatcherBackend::Row` dispatch in `MatchGeneratorDriver::skip_matching_with_hint` now passes the hint through to the Row backend. A regression test `row_skip_matching_with_incompressible_hint_uses_sparse_prefix` covers this. Do not flag Row as ignoring incompressible hints or defaulting to dense-only skip.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/match_generator.rs:1675-1701
Timestamp: 2026-04-10T07:20:51.122Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd), `DfastMatchGenerator::skip_matching` (the dense/non-sparse path, i.e. when `used_sparse` is false) backfills the previous-slice tail (`current_abs_start.saturating_sub(DFAST_MIN_MATCH_LEN + 3) .. current_abs_start`) before calling `insert_positions(current_abs_start, current_abs_end)`. This mirrors the `skip_matching_dense` backfill and `HcMatchGenerator::backfill_boundary_positions` patterns, ensuring positions at block boundaries become hashable as soon as the next slice extends history. A regression test `dfast_dense_skip_matching_backfills_previous_tail_for_next_block` covers immediate cross-boundary matching after a dense skip. Do not flag the absence of this backfill as a missing step.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/match_generator.rs:457-463
Timestamp: 2026-04-11T07:48:12.353Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd, PR `#99`), `MatchGeneratorDriver::skip_matching_for_dictionary_priming` calls `row_matcher_mut().skip_matching_with_hint(Some(false))` for the `MatcherBackend::Row` case — explicitly requesting dense seeding, consistent with Simple (`skip_matching_with_hint(Some(false))`) and HashChain (`skip_matching(Some(false))`) backends. Do not flag this as using an implicit/unhinted path or suggest reverting to `skip_matching()`.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T21:51:56.626Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test `copy_bytes_overshooting_preserves_prefix_for_runtime_chunk_lengths` (or equivalent) includes a misaligned extra-capacity case that uses `add(1)`-offset pointers and a `chunk_plus_one` length to exercise the rounded-up wildcopy overshoot path (where `copy_multiple > copy_at_least`) and validates prefix correctness. Do not flag the absence of a misaligned-pointer case in this test — it is present by design.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-10T12:52:14.220Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd), `HcMatchGenerator::skip_matching`'s dense-tail reseed (the `Some(true)` / sparse incompressible path) iterates position-by-position over `tail_start..current_abs_end` and skips positions where `(pos - current_abs_start) % INCOMPRESSIBLE_SKIP_STEP == 0`. This prevents sparse-grid positions already indexed in the sparse pass from being reinserted and creating self-loop chain entries. A regression test `hc_sparse_skip_matching_does_not_reinsert_sparse_tail_positions` (line ~4086) covers this invariant. Do not flag the absence of a bulk `insert_positions(tail_start, current_abs_end)` call in the sparse-hint dense-tail path as a missing optimization.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/match_generator.rs:1682-1687
Timestamp: 2026-04-09T23:59:08.161Z
Learning: In `zstd/src/encoding/match_generator.rs` (structured-world/structured-zstd), `DfastMatchGenerator::skip_matching_dense` backfills the previous-slice tail (`max(current_abs_start - 3, history_abs_start) .. current_abs_start`) before seeding the current slice via `insert_positions`. This ensures that positions at internal priming-slice boundaries become hashable as soon as the next slice extends history, keeping cross-slice dictionary priming fully dense. The pattern mirrors `HcMatchGenerator::backfill_boundary_positions`. Do not flag the absence of this backfill as a missing step in `skip_matching_dense`.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T21:51:51.926Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test suite for `copy_bytes_overshooting` includes a misaligned extra-capacity case that exercises the rounded-up wildcopy path (where `copy_multiple > copy_at_least`) and validates prefix correctness for that scenario. Do not flag the absence of a misaligned/overshooting extra-capacity sub-case as missing test coverage.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 99
File: zstd/src/encoding/frame_compressor.rs:779-805
Timestamp: 2026-04-11T07:48:58.281Z
Learning: In `zstd/src/encoding/frame_compressor.rs` (structured-world/structured-zstd, PR `#99`), a temporary compatibility guard exists for sub-256-byte compressed payloads: the 1-byte-FCS single-segment form is not yet fully C-FFI compatible for payloads below 256 bytes, and a compat guard was added to handle this case while the path is hardened. Do not flag this guard as unnecessary.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-08T20:26:15.902Z
Learning: In `zstd/src/decoding/ringbuffer.rs` (structured-world/structured-zstd), the test `copy_bytes_overshooting_covers_all_copy_strategies` derives copy lengths from a helper `active_chunk_size_for_tests()` (not hardcoded values) so that single-chunk, multi-chunk, and sub-chunk (fallback) cases adapt to whichever SIMD backend width is active at runtime (AVX-512/AVX2/SSE2/NEON/scalar). Do not flag hardcoded test lengths as missing coverage for other backends — the test is backend-adaptive by design.

Learnt from: polaz
Repo: structured-world/structured-zstd PR: 0
File: :0-0
Timestamp: 2026-04-06T01:40:24.378Z
Learning: In `zstd/benches/compare_ffi.rs` (structured-world/structured-zstd), Rust FastCOVER trains with the post-finalization content budget in both the `REPORT_DICT_TRAIN` emission path (around lines 208-225) and the Criterion benchmark path (around lines 266-280). Both paths were aligned in commit 8622344. Do not flag these ranges as using inconsistent budget values.

@polaz polaz requested a review from Copilot April 11, 2026 11:58
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@zstd/src/encoding/match_generator.rs`:
- Around line 4308-4345: The tests hard-code accelerated enums
(HashMixKernel::X86Sse42 / HashMixKernel::Aarch64Crc) which bypass runtime
selection; change them to call detect_hash_mix_kernel() under the same
CPU-feature guard (is_x86_feature_detected! / is_aarch64_feature_detected!) and
assert that detect_hash_mix_kernel() returns the expected accelerated variant,
then use that detected kernel in hash_mix_u64_with_kernel for the comparison
(instead of the hard-coded enum); keep the existing accelerated unsafe call
(hash_mix_u64_sse42 / hash_mix_u64_crc) as the reference value but only run the
assert if the detected kernel matches the accelerated variant.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4deef961-5e86-49d4-86a2-ad2dc4642036

📥 Commits

Reviewing files that changed from the base of the PR and between 904d2b0 and 46927db.

📒 Files selected for processing (1)
  • zstd/src/encoding/match_generator.rs

Comment thread zstd/src/encoding/match_generator.rs
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment thread zstd/src/encoding/match_generator.rs
Comment thread zstd/src/encoding/match_generator.rs Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@polaz polaz merged commit e8ad7c1 into main Apr 11, 2026
17 checks passed
@polaz polaz deleted the perf/#71-crc-hash-gating branch April 11, 2026 12:31
@sw-release-bot sw-release-bot Bot mentioned this pull request Apr 11, 2026
Copy link
Copy Markdown

@sw-release-bot sw-release-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'structured-zstd vs C FFI (x86_64-gnu)'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.30.

Benchmark suite Current: 33b482f Previous: ae02906 Ratio
compress/level4-row/small-4k-log-lines/matrix/pure_rust 0.069 ms 0.053 ms 1.30
compress/level4-row/low-entropy-1m/matrix/pure_rust 9.264 ms 5.554 ms 1.67

This comment was automatically generated by workflow using github-action-benchmark.

CC: @polaz

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.

2 participants