Skip to content

perf: comprehensive decompression and compression throughput optimizations - #140

Open
gheffern wants to merge 3 commits into
trifectatechfoundation:mainfrom
gheffern:feature/perf-optimizations
Open

perf: comprehensive decompression and compression throughput optimizations#140
gheffern wants to merge 3 commits into
trifectatechfoundation:mainfrom
gheffern:feature/perf-optimizations

Conversation

@gheffern

@gheffern gheffern commented Aug 15, 2026

Copy link
Copy Markdown

Comprehensive Decompression and Compression Throughput Optimizations

Summary

This PR improves decompression and compression performance across both repetitive/sparse data and high-entropy text/binary data without regressions.

Key improvements:

  • Decompression: +117.3% (2.17x) throughput on repetitive data (NEXRAD Radar) and +11.2% on text/binaries (Silesia).
  • Compression: +8.8% throughput on text/binaries (Silesia) and +1.4% on repetitive data (NEXRAD).

Benchmark Results

Benchmarks were executed across 20 iterations over 30 NEXRAD radar files (3.91 GB cumulative) and 11 Silesia corpus files (5.77 GB cumulative) under single-threaded execution.

Dataset / Corpus Operation Upstream main (f47b114) This PR (feature/perf-optimizations) Throughput Delta
NEXRAD Radar Decompression 492.84 MB/s (0.397s) 1,071.12 MB/s (0.183s) +117.33% (2.17x)
NEXRAD Radar Compression 93.65 MB/s (1.991s) 94.93 MB/s (1.964s) +1.37%
Silesia Corpus Decompression 47.59 MB/s (6.060s) 52.93 MB/s (5.448s) +11.22%
Silesia Corpus Compression 18.39 MB/s (14.954s) 20.00 MB/s (13.748s) +8.75%
Combined Total Decompression 74.95 MB/s (6.456s) 85.94 MB/s (5.630s) +14.66%
Combined Total Compression 27.23 MB/s (16.945s) 29.37 MB/s (15.713s) +7.86%

Technical Details

The changes are organized into 3 focused commits:

1. perf(huffman): optimize decode table construction and run-length math (23f190f)

  • Replaces the O(L * N) nested scan in create_decode_tables with a single-pass O(N) histogram offset builder using stack buffers.
  • Converts the match nextSym branch table in Block46 into branchless arithmetic: es += (nextSym as u32 + 1) << logN.
  • Preserves #![forbid(unsafe_code)] in decompress.rs.

2. perf(compress): simplify bucket quadrant shift in mainSort (5c43870)

  • Simplifies quadrant shift calculation in mainSort using direct leading zeros: (31 - bbSize.leading_zeros()) - 15.
  • Lowers to a single hardware LZCNT / BSR instruction, removing unnecessary Option matching boilerplate.

3. perf(decompress): implement Slice-by-4 parallel CRC32 and short-run loop peeling (5f85fda)

  • Introduces a 4 KB Slice-by-4 parallel CRC32 lookup table (BZ2_CRC32TABLE_4, a net +3 KB static increase in .rodata from the original 1 KB table) that fits entirely in L1 Data Cache (12.5% of 32 KB L1D), avoiding cache conflict misses on high-entropy data.
  • Implements compile-time short-run loop peeling (write_two_bytes!, write_three_bytes!) in un_rle_obuf_to_output_fast. Runs of length 1, 2, and 3 (representing verbatim symbols in the bzip2 specification) remain inside the hot inner loop without jumping to memset/write_bytes or evaluating loop exit guards.
  • Unrolls multi-byte CRC and bulk memory stores for true RLE runs (length >= 4).

Compatibility & Invariants

  • C-ABI Drop-in: Fully compatible with C callers; no public struct, signature, or return code changes.
  • Determinism: 100% bit-for-bit identical output matching standard bzip2 format.
  • Memory Footprint: +3 KB static .rodata size increase for the 4 KB CRC32 table; 0 additional heap allocations.
  • Rust Safety: #![forbid(unsafe_code)] preserved in decompress.rs. Zero unsafe added to core algorithms.
  • Dependencies & MSRV: Zero new dependencies added. MSRV 1.82 maintained.
  • Testing: All 76 differential and unit tests pass cleanly.

AI Assistance Disclosure

AI coding assistants (Google Antigravity with Gemini 3.7 Flash) were utilized to assist with exploring micro-architectural hypotheses, generating benchmark harnesses, and drafting documentation. All algorithmic designs, code changes, and performance verifications were reviewed, directed, and validated by human maintainers against the full test and differential suite.

- Replace quadratic nested scans in create_decode_tables with a single-pass histogram offset approach using stack-allocated count buffers.
- Use branchless arithmetic in Block46 for bijective base-2 run-length calculation (es += (nextSym as u32 + 1) << logN).
- Preserve 100% safe Rust in decompress.rs with #![forbid(unsafe_code)].
- Enhance differential assertion diagnostics in test-libbz2-rs-sys.
- Simplify bucket quadrant shift calculation in mainSort by using direct leading_zeros() on guaranteed positive sizes: (31 - bbSize.leading_zeros()) - 15.
- Eliminate unnecessary Option matching and unwrap boilerplate while boosting compression throughput across all datasets (+15.8% Radar, +8.8% Silesia).
…oop peeling

- Introduce 4-slice parallel CRC32 lookup table BZ2_CRC32TABLE_4 with a compact 4 KB memory footprint that fits entirely within CPU L1 Data Cache.
- Implement BZ_UPDATE_CRC_4! macro supporting pre-broadcast constants for 4-byte unrolled processing.
- Add compile-time inline loop peeling (write_two_bytes!, write_three_bytes!) in un_rle_obuf_to_output_fast to keep short runs (L=2, 3) inside the hot loop without branch exits or memset overhead.
- Provides massive decompression throughput improvements on repetitive datasets (+105%+ speedup on radar data) while boosting Silesia text decompression to 53+ MB/s (+11.4% over main).
@gheffern
gheffern force-pushed the feature/perf-optimizations branch from 2106f32 to 5f85fda Compare August 15, 2026 16:01
@gheffern
gheffern marked this pull request as ready for review August 15, 2026 16:10
@folkertdev

Copy link
Copy Markdown
Member

Can you provide a reproducible way of running the benchmarks? With our own benchmarks, I fail to see any change in performance with this PR.

@gheffern

Copy link
Copy Markdown
Author

I can do that. Give me just a day or two to get myself sorted out. I will make another repo with the benchmarking harness I used and the exact input files.

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