Repository navigation
Peek RAR5 Huffman codes with one load and decode them inline - #107
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 -sarchive. Two things in that path cost more than they need to:HuffmanState::decodewas an out-of-line call per symbol, saving and restoring registers each time. It is now#[inline(always)], likedecode_peekedinside it.peek15built 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 teston hosted runners, MB/s, with this branch rebased onto 0.12.3 andmasterat 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:-m3 -s-m5 -s-m3(WinRAR's default)-m3 -s-m5 -s-m3Extracting to disk moves less, as writing the files takes most of the time there: Linux
-m3 -sgoes 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 warningsandfmtare clean.cargo test -p rars-cli --locked, on an M1 Mac instead, and it passes.scripts/reference-corpus.pywith 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