AET Adaptive Entropy Transformer
AetherArch Benchmarks
Performance measurements and tuning workflows for the aet archiver.
Workload Matrix
Use the checked-in matrix runner for repeatable text, log, executable/binary, image, and tiny-file measurements across all compression profiles:
pwsh ./scripts/benchmark-matrix.ps1 `
-Binary C:\path\to\aet-aether-opt-019fb2fb.exe `
-DatasetRoot C:\datasets\aether `
-Iterations 10 `
-OutputCsv benchmark-matrix.csv
The dataset root contains text, logs, binaries, images, and tiny
directories. The runner records input/archive bytes, ratio, compression and
extraction time, and throughput for archival, balanced, and fast.
Missing workload directories are reported and skipped. Keep published results
separate from historical values in docs/BENCHMARKS.md.
Decompression
The compression matrix above times one extraction per case — enough to catch a regression, not enough to reason about read speed. Two decompression-specific tools sit alongside it.
Per-stage benchmarks
cargo bench -p aether-core --bench decompression
Four groups, each isolating a stage so a change can be attributed rather than lost in end-to-end noise:
| Group | What it measures |
|---|---|
decode/* | The range-decoder hot loop per predictor. This is the stage that dominates every predictor-backed block. |
method/* | router::decompress_chunk per compression method, on payloads produced by the real encoder. |
transform/* | The inverse transforms: BWT+MTF, RLE, LZ77, byte-plane. |
archive/* | Metadata parsing, whole-archive extraction, verify. |
Workload matrix
pwsh ./scripts/decompression-matrix.ps1 `
-Binary C:\path\to\aet.exe `
-DatasetRoot C:\datasets\aether `
-Repetitions 5 `
-Threads 1,2,4,0 `
-OutputCsv decompression-matrix.csv
Same dataset layout as the compression matrix (text, logs, binaries,
images, tiny). Differences that matter:
- Compression runs once per case as untimed setup.
- Extraction is repeated and reported as minimum and median. Compare the minimum across builds — it is the run least polluted by whatever else the host was doing.
- Thread counts are swept, so scaling is measured rather than assumed.
verify(decode without writing files) and single-file extraction (random access via the block index) are measured alongside full extraction; they are separate user-visible operations with different costs.- Throughput is reported over decompressed bytes. An archive-size rate makes a decompressor look faster the better the compressor did.
Measuring on a busy machine
Wall-clock on a shared development host varies by a factor of two to four between runs — larger than most effects worth measuring. Three rules:
- Compare inside one process. Where both code paths can be compiled together, run them alternately in one binary and take the minimum of several repetitions. Background load then affects both arms equally.
- Never compare across separate benchmark runs. Criterion's
--save-baselineis only trustworthy when both arms ran under the same machine conditions. - Watch the ratio, not the absolute. A 40% swing in both arms of the same run is the host, not the code.
See docs/perf/decompression.md for the
analysis these tools were built to support.
Profile-Guided Optimization
AetherArch's hot path is byte-level entropy coding: millions of small
predict() / range-coder calls per second through
aether-core/src/coding/rans.rs and aether-core/src/entropy/neural_ssm.rs.
Branch direction and inlining choices in those files are exactly what PGO
biases well, so we ship a one-shot wrapper.
One-liner
pwsh ./scripts/pgo.ps1
The script:
- Verifies
cargo-pgoandllvm-profdataare available (instructions printed if not). - Builds an instrumented
aetintotarget/<host>/release-pgo/. - Runs a training workload — compress + extract of
english.txt,source.rs, andmixed.jsonfromtests/fixtures/large/, three iterations each, into a temp dir that's cleaned up afterward. - Rebuilds the same crate with the merged profile via
cargo pgo optimize buildand prints the final binary path plus allvm-profdatasummary of the merged profile.
Expected wins
Based on the Rust PGO literature (Rust compiler itself, ripgrep, hyperfine),
expect roughly 5–15% throughput improvement on encode and decode for
predictor- and range-coder-bound workloads. Not measured in this repo yet —
plug in aet bench --compare against the PGO binary if you want concrete
numbers for your hardware.
When to re-run
Re-run scripts/pgo.ps1 whenever you materially change:
aether-core/src/coding/rans.rs(range coder hot loop, CDF construction)aether-core/src/entropy/neural_ssm.rsor otherProbabilityPredictorimpls- The routing cascade in
aether-core/src/pipeline/router.rs - Branch-heavy code on the compress / decompress paths
Cosmetic edits (docstrings, formatting, test-only code) don't need a rebuild; the previous PGO binary stays accurate.
Not a default build
PGO is not part of cargo build --release. The standard release profile
is unchanged — same flags, same target dir, same output. PGO artifacts live in
the dedicated release-pgo profile under a separate output directory so
instrumentation runtime never leaks into normal builds.
If you cargo build --profile release-pgo directly (without the wrapper) you
get a plain release build that just happens to live in the wrong folder — no
PGO. Always go through scripts/pgo.ps1.