lbunzip2 — design
Class:
design· Function:lbunzip2(parallel bzip2 CLI). Strict: the shipped shape, every claim a realfile:symbol. Run it vialbunzip2-guide.md; why bzip2 saturates cleanly inlbunzip2-reasoning.md. The in-memory /Read-trait library twins arelbzip2-readers-design.md.
What it is
lbzip2/src/bin/lbunzip2.rs — a pure-Rust CLI decoder for the stock .bz2 format, decoding independent BWT blocks across every core. lbunzip2 in.bz2 [out] (strips the .bz2 extension when out is omitted).
The exact dataflow
bzip2 is a stream of independent blocks (100 KB–900 KB uncompressed each, level 1–9), every block a self-contained Huffman + MTF + BWT unit prefixed by the 48-bit magic 0x314159265359 at an arbitrary bit offset. That independence is the whole parallelism story, and lbunzip2 rides the shared gatling ordered engine (gatling::gatling::ordered::run_ordered_sink, gatling/src/gatling_ordered.rs:113) end to end — there is no hand-rolled pool.
-
Producer (one dispatch thread). Runs on the engine's dispatch thread so its I/O overlaps decode. It reads 8 MB compressed chunks (
CHUNK_SIZE), prepends the carry (the previous chunk's undecoded tail, seeded with the 4-byteBZhheader), and callschunk::split_chunk(lbzip2/src/chunk.rs:35) to cut the chunk into per-block segments. It yields one segment at a time asSegIn { data: Arc<Vec<u8>>, start_bit, end_bit, max_blocksize }(lbunzip2.rs:88) — theArckeeps the chunk buffer alive across every segment referencing it (the ownership-based replacement for the old raw-pointer-into-a-recycled-slot). -
Block-boundary scan.
split_chunklocates block magics with the bit-level sliding-window scanner inlbzip2/src/block_scan.rs:split_boundaries_parallel(block_scan.rs:279) fans the N−1 nominal split points across cores viagatling_for_each, each core forward-scanning for the next magic andquick_verify_block-ing 73 header bits (block_scan.rs:214) to reject false-positive magic patterns inside compressed data — no full decode needed. -
N map workers (self-dispatch, no barrier). Each pulls the next segment and runs
chunk::decode_segment_checked(lbzip2/src/chunk.rs:117): Huffman → MTF → inverse-BWT, then a per-block CRC-32 check. A CRC mismatch is fatal — the worker printscorrupt inputand exits non-zero rather than emit silently-truncated bytes (lbunzip2.rs:270). -
Ordered sink.
WriteSink::emit(lbunzip2.rs:110) writes each decoded segment in strict producer order to a 4 MBBufWriter. The engine's counting-permit pool bounds in-flight memory tocapsegments, so resident decoded output is a handful of segments — never the whole file.
The segmentation floor (a real correctness fix, not tuning)
n_segments = n_workers.max(2) (lbunzip2.rs:173). The producer holds back the last segment of every non-final chunk as carry (its trailing block may continue into the next chunk), decoding decode_segments = n − 1. With a single segment split_chunk returns None for non-last chunks, so the producer would discard those bytes and only the final chunk would ever decode — a silent truncation to the last ~8 MB (and a bogus "single-core faster than all cores" bench). Flooring at 2 means even LBZIP2_THREADS=1 streams the whole file (segments decoded one at a time, in order) while worker parallelism stays exactly n_workers.
Whereabouts
| Thing | file:symbol |
| CLI entry / producer / sink | lbzip2/src/bin/lbunzip2.rs:120 (main) |
| chunk split into segments | lbzip2/src/chunk.rs:35 (split_chunk) |
| parallel block-magic scan | lbzip2/src/block_scan.rs:279 (split_boundaries_parallel) |
| header quick-verify (73 bits) | lbzip2/src/block_scan.rs:214 (quick_verify_block) |
| CRC-checked block decode | lbzip2/src/chunk.rs:117 (decode_segment_checked) |
| ordered streaming sink | gatling/src/gatling_ordered.rs:113 (run_ordered_sink) |
| worker count / core detect | lbzip2/src/bin/lbunzip2.rs:38 (physical_cores) |
Saturation state (just-landed)
lbunzip2 sits at ~7.8–11.5/12 cores on the quiet box — the highest of the DEFLATE family's siblings because bzip2's block independence needs no writer trick (the per-block work dwarfs the ordered write). Real cores_busy lands in the README.md A/B/C mashup on the heavy-bench wave; nothing is fabricated here. Note the honest loss recorded in the README: mature C lbzip2 still edges us on raw bzip2, while we crush serial bzip2 ~10×.