Skip to content

perf: replace lzma-rs with lzma-rust2 and enable zlib-rs backend - #3

Open
maboloshi wants to merge 1 commit into
ATRAPSLLC:mainfrom
maboloshi:lzma-rust2
Open

perf: replace lzma-rs with lzma-rust2 and enable zlib-rs backend#3
maboloshi wants to merge 1 commit into
ATRAPSLLC:mainfrom
maboloshi:lzma-rust2

Conversation

@maboloshi

Copy link
Copy Markdown

Switch LZMA/LZMA2 decoding from lzma-rs to lzma-rust2, and flate2 to the zlib-rs backend

Motivation

While extracting Inno Setup installers (solid LZMA1/LZMA2 chunks and setup-0
blocks) for a Scoop-like package manager, we measured the pure-Rust lzma-rs
decoder to be the dominant cost of decompression. lzma-rust2 is a
maintained, actively optimized LZMA/LZMA2 decoder that in our benchmarks
(21 MB LZMA1 stream) decodes roughly 1.4x faster than lzma-rs while
remaining 100% Rust.

Similarly, flate2's default rust_backend (miniz_oxide) is replaced with the
newer, faster zlib-rs backend for Compression=zlib installers.

Changes

  • Cargo.toml: replace lzma-rs = "0.3.0" with
    lzma-rust2 = { version = "0.18", default-features = false, features = ["std", "optimization"] };
    switch flate2 to default-features = false, features = ["zlib-rs"].
    lzma-rs is kept as a dev-dependency only, because the chunk reader's
    tests still use lzma_rs::lzma_compress to build compressed fixtures.
  • src/decompress/block.rs (decompress_inno_lzma1): decode with
    lzma_rust2::LzmaReader::new_mem_limit + std::io::copy instead of
    lzma_rs::lzma_decompress_with_options + UnpackedSize::UseProvided(None).
    Inno's non-standard 5-byte LZMA1 properties header is padded with the
    8-byte unknown-size sentinel (u64::MAX) to form the 13-byte LZMA-Alone
    header lzma-rust2 expects; the end-of-payload marker terminates the stream.
  • src/extract/chunk.rs: same swap for decompress_lzma1, and the LZMA2
    branch now uses lzma_rust2::Lzma2Reader (32 MiB dictionary default; Inno's
    1-byte property prefix is skipped) + io::copy.

Behavior notes

  • The decoder stops at the end-of-payload marker, so trailing bytes after the
    stream (CRC, padding) are left unread — the same data is produced as before.
  • No changes to the public API; error mapping (Error::Decompress) is
    preserved.
  • Verified against real-world installers (LZMA1 Compression=lzma/lzma2
    chunks, setup-0 blocks, solid chunks shared across files) with
    tree-identical extraction results, and the existing unit tests pass.

Switch the LZMA/LZMA2 decoder from lzma-rs to the faster, maintained
lzma-rust2 (~1.4x faster on LZMA1 in our benchmarks, still pure Rust),
and enable the zlib-rs backend for flate2 instead of the default
miniz_oxide.

Inno's non-standard 5-byte LZMA1 properties header is padded with the
8-byte unknown-size sentinel (u64::MAX) to form the 13-byte LZMA-Alone
header lzma-rust2 expects; the LZMA2 branch uses Lzma2Reader with a
32 MiB dictionary default. lzma-rs is kept as a dev-dependency because
the chunk reader tests still build fixtures with lzma_rs::lzma_compress.

No public API changes; Error::Decompress mapping preserved. All 79 unit
tests pass.
Copilot AI lite review requested due to automatic review settings August 15, 2026 08:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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