Benchmarks - YadeWira/ultra-fast-lzma2 GitHub Wiki

Benchmarks

The lz6 bakeoff

The tables below come from the bakeoff maintained by the lz6 project (bakeoff/VS_CODECS.md, commit 12d8fe5), which runs every codec through one harness: lzbench 3d22c41, default makefile, GCC 14.2, one thread, memory to memory, -t1,1, results aggregated per file weighted by size. Machine: 2x Xeon E5-2697A v4, shared, run-to-run noise about 5%. uf-lzma2 enters through its own lzbench patch.

fastlzma2 is lzbench's own build of fast-lzma2 1.0.1, which compiles the C files only and therefore decodes with the C decoder. uf-lzma2 is the same compressed data read by the assembler decoder: the compressed sizes are identical on every file, so the two rows differ only in how they are built.

Silesia, 12 files, per file

codec ratio compress decompress
uf-lzma2 L10 (asm) 22.97% 3.3 MB/s 110.5 MB/s
fastlzma2 L10 (C) 22.97% 3.3 MB/s 81.0 MB/s
xz L9 23.02% 2.5 MB/s 110.3 MB/s
brotli L11 23.75% 0.5 MB/s 358.6 MB/s
uf-lzma2 L5 (asm) 24.12% 6.1 MB/s 107.0 MB/s
zstd L19 24.96% 2.7 MB/s 789.5 MB/s
lz6 seq -15 26.39% 2.2 MB/s 399.0 MB/s
uf-lzma2 L1 (asm) 27.84% 18.1 MB/s 96.4 MB/s
lizard L49 28.62% 1.9 MB/s 1197.6 MB/s
misa77 L1 42.65% 51.1 MB/s 5153.7 MB/s

The assembler decoder is worth +36% at L10, +37% at L5 and +48% at L1 over the C one, for exactly the same bytes.

AIT A-H, 8 files

codec ratio decompress
lz6 seq -15 39.55% 320.4 MB/s
brotli L11 53.60% 210.5 MB/s
uf-lzma2 L10 (asm) 53.80% 63.9 MB/s
xz L9 54.16% 63.6 MB/s
zstd L19 55.97% 1052.6 MB/s

AIT is lz6's training corpus, and its gap is almost entirely one file. D is 2 MB of pseudo-random output that lz6 recognises and stores as the generator's seed, in 7 bytes; every LZ codec stores it at 100%. Without D:

codec AIT without D
brotli L11 45.27%
uf-lzma2 L10 45.50%
xz L9 45.92%
lz6 seq -15 46.66%
zstd L19 48.06%

lz6's remaining advantage is on E and F, numeric data it splits into byte planes. The standard xz delta filter, the compatible candidate, makes both files larger at every distance. See Findings.

uf-lzma2, fast-lzma2 and the LZMA SDK side by side

The three are LZMA2 encoders writing the same standard format, so this is the most direct comparison. Silesia as one solid stream (212 MB), two compression threads, one decompression thread, best of three, same machine; the raw rows are in bench/data. Rows are matched at each library's best ratio (~22.97%).

ratio compress decompress
uf-lzma2 1.4.0 L10 22.96% 5.7 MB/s 110.9 MB/s (asm)
fast-lzma2 1.0.1 L10 22.96% 5.8 MB/s 82.1 MB/s (C build)
LZMA SDK 26.03 L7 22.98% 3.8 MB/s 83.1 MB/s

Ratio and compression. uf-lzma2 and fast-lzma2 write identical bytes at levels 1-10, so they share every ratio and differ in compression speed only by noise (up to 11% either way). The SDK is a different encoder: it wins the fast end with its hash-chain match finders but its ratio plateaus there, and at the high end uf-lzma2 reaches a slightly better ratio at a higher speed (L10, 22.96% at 5.7 MB/s, against the SDK's best L7, 22.98% at 3.8 MB/s). The full per-level curve is in Two threads, solid.

Decompression is a property of the format, not the encoder. All three decode the same standard LZMA2; built like with like they tie (one thread, all with the C decoder: SDK 76.5, fast-lzma2 76.1, uf-lzma2 75.5 MB/s). uf-lzma2 ships the assembler decoder, worth +35-48% for exactly the same bytes, and adds an ARM64 one; fast-lzma2 and the SDK have assembler decoders of their own, which the C-only builds above do not use. So the decompress column compares builds, not encoders: read it with Reading these numbers.

Level 11, measured here

Level 11 is newer than the bakeoff above, so these numbers are this project's own: one thread, per file, the same machine. Compression and ratio with bench/curve; decompression best of seven in round-robin passes, assembler decoder.

level 10 level 11
Silesia ratio 22.9657% 22.8760%
Silesia compression 3.23 MB/s 1.10 MB/s
Silesia decompression 118.0 MB/s 116.4 MB/s
AIT ratio 53.80% 52.64%
AIT decompression 60.1 MB/s 59.8 MB/s

A single decompression pass showed -3.6% on Silesia; best of seven in round robin shows -1.4%, so the true cost is within a few percent at most. Streaming compression ignores the search, so there level 11 behaves as level 10.

Reading these numbers

Compare ratio at equal speed, not level at equal level. Level 5 means different things in different codecs.

Build like with like. This library, 7-Zip and xz all have assembler LZMA decoders. A comparison where one side is built without its assembler decoder credits the difference to the wrong design.

Know the aggregation. lzbench reports per file; an archiver compresses a solid stream. File by file, the useful dictionary is capped by the largest file (51 MB in Silesia), so levels that differ only in dictionary size can produce identical output. bench/curve -s measures the solid case.

uf-lzma2 against the LZMA SDK, solid

Measured with bench/curve: Silesia as one solid stream, one thread, best of three, all three arms built with the C decoder so that decompression is compared like with like.

target ratio LZMA SDK 26.03 uf-lzma2 1.1.0 compression speed
~0.2758 L1: 19.09 MB/s L2: 14.65 MB/s SDK -23%
~0.2653 L3: 16.40 MB/s L3: 10.02 MB/s SDK -39%
~0.2339 L6: 2.96 MB/s L7: 4.53 MB/s uf-lzma2 +53%
~0.2298 L7: 2.51 MB/s L10: 3.19 MB/s uf-lzma2 +27%

There is a crossover. The SDK wins the fast end with its hash-chain match finders, then drops from 11.75 to 2.90 MB/s between its levels 4 and 5 when it switches to the optimal parser with bt4. The radix match finder has no such cliff, so past the crossover it is ahead. That is what fast-lzma2's README promises: "20% to 100% speed gain at the higher levels". Decompression is a tie: 76.5, 76.1 and 75.5 MB/s averaged over the levels for the SDK, fast-lzma2 and uf-lzma2.

Two threads, solid: the README graph

Silesia as one solid stream, two compression threads, best of three, on the same machine. fast-lzma2 1.0.1 writes the same bytes as uf-lzma2 at levels 1-10, so it has only a speed column; the two differ by up to 11% either way, which is noise. The LZMA SDK splits its two threads as 7-Zip's -mmt2 does: from level 5 one block with a match-finder thread, below it one block per thread. The raw rows are in the repository's bench/data.

level uf-lzma2 1.4.0 ratio MB/s fast-lzma2 1.0.1 MB/s LZMA SDK 26.03 ratio MB/s
1 27.90% 28.5 28.4 27.88% 40.4
2 26.63% 25.2 23.9 27.11% 38.0
3 25.53% 16.9 17.7 26.60% 27.4
4 24.65% 14.5 14.8 26.41% 20.5
5 24.18% 11.0 12.2 23.39% 4.6
6 23.65% 9.5 8.6 23.38% 4.1
7 23.35% 8.2 7.9 22.98% 3.8
8 23.18% 7.1 7.0 22.97% 3.7
9 23.07% 6.4 6.6 22.97% 3.7
10 22.96% 5.7 5.8
11 22.96% 1.8

At equal ratio uf-lzma2 is 77% faster around 23.4% (its level 7 against the SDK's 5) and 49% faster around 22.97% (level 10 against 7). Level 11 gains only 4,755 bytes on the solid stream, since its search chooses one lc/lp/pb setting per input; file by file it gains 0.39% (see above).