Skip to content

Peek RAR5 Huffman codes with one load and decode them inline - #107

Merged
bitplane merged 1 commit into
bitplane:masterfrom
tiendc:rar5-x86
Oct 26, 2026
Merged

bitplane merged 1 commit into
bitplane:masterfrom
tiendc:rar5-x86

Conversation

@tiendc

@tiendc tiendc commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Decoding a solid RAR5 archive written by RAR itself spends most of its time in Huffman decoding. Under perf on an x86-64 runner it was 56% of a RAR 7.23 -m3 -s archive. Two things in that path cost more than they need to:

  • The decoder was not inlined. HuffmanState::decode was an out-of-line call per symbol, saving and restoring registers each time. It is now #[inline(always)], like decode_peeked inside it.
  • peek15 built its word a byte at a time. It matched the remaining input as a slice of at least three bytes and assembled the word one byte at a time. When four or more bytes remain, it now does one four-byte load and shifts out the 15 bits, which start at most 7 bits in. Nearer the end it takes the existing path, so truncation and incremental-input behaviour are unchanged.

rars --threads 1 test on hosted runners, MB/s, with this branch rebased onto 0.12.3 and master at 0.12.3. The archives were written by RAR 7.23 from one folder of ~200 MB (5,500 files: source text, incompressible blocks, mostly-zero files) and timed three rounds in turn:

master inline only this PR reference
Linux, -m3 -s 264–267 275 307–308 unrar 299–354
Linux, -m5 -s 266–269 277–278 308–310 unrar 351–357
Linux, -m3 (WinRAR's default) 463–468 480–481 506–511 unrar 363–367
Windows, -m3 -s 230–241 239–244 268–269 7-Zip 434–441
Windows, -m5 -s 232–243 236–245 261–269 7-Zip 332–442
Windows, -m3 363–371 377–386 398–401 7-Zip 766–779

Extracting to disk moves less, as writing the files takes most of the time there: Linux -m3 -s goes from 132–133 to 141–142 MB/s; on Windows the change is within noise. The macOS bench job did not get a runner this time.

Solid archives gain most: they keep incompressible data inside the compressed stream, so they have more symbols per byte. Without solid, RAR stores such files instead.

Validation, on top of 0.12.3:

  • cargo test -p rars --release: 2633 tests pass; cargo test -p rars-cli: 364 pass.
  • clippy -D warnings and fmt are clean.
  • CI passes on my fork, except the macOS CLI job, which never got a runner (four attempts were cancelled before any step ran). I ran its step, cargo test -p rars-cli --locked, on an M1 Mac instead, and it passes.
  • scripts/reference-corpus.py with RAR 7.23 and 6.24, including the extended cases from CLI extracts RAR 1.5–4 Unix symbolic links as regular files #105 and every damage variant: all 1176 cases agree with UnRAR 7.23.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bitplane
bitplane merged commit e2415a2 into bitplane:master Oct 26, 2026
48 checks passed
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