Squinch benchmarks

This page is generated by util/update-benchmark-doc.sh. It runs make bench, refreshes the tables, and regenerates every chart in doc/assets/*.img/.

Memory use

unsquinch and squinch d use two I/O buffers, the decoded stream window, and the decompressor context:

2 * I/O buffer size + window size + sizeof(struct SquinchDecompressor)

The table below shows this total without the small, platform-dependent context size, allocator overhead, or FILE buffers. Both I/O buffers use the size shown in the column heading. Values are rounded to the nearest kiB.

window 512 bytes I/O 4 kiB I/O 64 kiB I/O 128 kiB I/O 256 kiB I/O
256 bytes 1 kiB 8 kiB 128 kiB 256 kiB 512 kiB
4 kiB 5 kiB 12 kiB 132 kiB 260 kiB 516 kiB
8 kiB 9 kiB 16 kiB 136 kiB 264 kiB 520 kiB
32 kiB 33 kiB 40 kiB 160 kiB 288 kiB 544 kiB
64 kiB 65 kiB 72 kiB 192 kiB 320 kiB 576 kiB

squinch c also uses two I/O buffers, its compressor context, the window, a look-ahead ring, and matcher arrays of (bucket count + window size) * sizeof(size_t). The default look-ahead size is min(window size, 1 kiB). Its total memory use is independent of the input size.

The encoder tables below include the history window, the default look-ahead ring, and matcher arrays. They assume an 8-byte size_t and omit the small, platform-dependent compressor context, allocator overhead, and FILE buffers. Values are rounded to the nearest kiB.

Default 65536 buckets:

window 512 bytes I/O 4 kiB I/O 64 kiB I/O 128 kiB I/O 256 kiB I/O
256 bytes 516 kiB 523 kiB 643 kiB 771 kiB 1027 kiB
4 kiB 550 kiB 557 kiB 677 kiB 805 kiB 1061 kiB
8 kiB 586 kiB 593 kiB 713 kiB 841 kiB 1097 kiB
32 kiB 802 kiB 809 kiB 929 kiB 1057 kiB 1313 kiB
64 kiB 1090 kiB 1097 kiB 1217 kiB 1345 kiB 1601 kiB

4096 buckets:

window 512 bytes I/O 4 kiB I/O 64 kiB I/O 128 kiB I/O 256 kiB I/O
256 bytes 36 kiB 43 kiB 163 kiB 291 kiB 547 kiB
4 kiB 70 kiB 77 kiB 197 kiB 325 kiB 581 kiB
8 kiB 106 kiB 113 kiB 233 kiB 361 kiB 617 kiB
32 kiB 322 kiB 329 kiB 449 kiB 577 kiB 833 kiB
64 kiB 610 kiB 617 kiB 737 kiB 865 kiB 1121 kiB

Using fewer matcher buckets causes a very slightly worse compression ratio, but decreases compression speed significantly. The tradeoff can save a lot of memory because the bucket table is allocated for every compressor.

Source code comparison

The full-tool rows count the complete command-line implementations in this repository snapshot: src/*.c for Squinch, programs/*.c plus lib/*.c for LZ4, and the GNU gzip top-level codec sources plus lib/*.c. The embed rows focus on the standalone codec files that would have to move into another code base. GNU gzip does not expose a similarly small embeddable API, so its embed rows count the codec-core files without the command-line entry point or gnulib support library.

Each table is ordered by code characters. Each chart is ordered by its displayed value, from small to large.

Embed compressor

Bar chart of Embed compressor code lines, sorted from small to large.

Bar chart of Embed compressor code characters, sorted from small to large.

target scope code lines code chars
Squinch compress.c Embed compressor 863 lines 20557 chars
GNU gzip core Embed compressor 1807 lines 37537 chars
LZ4 block API Embed compressor 2208 lines 69392 chars

Embed decompressor

Bar chart of Embed decompressor code lines, sorted from small to large.

Bar chart of Embed decompressor code characters, sorted from small to large.

target scope code lines code chars
Squinch decompress.c Embed decompressor 842 lines 20727 chars
GNU gzip core Embed decompressor 2115 lines 34631 chars
LZ4 block API Embed decompressor 2208 lines 69392 chars

Full tools

Bar chart of Full tools code lines, sorted from small to large.

Bar chart of Full tools code characters, sorted from small to large.

Bar chart of Full tools stripped binary sizes, sorted from small to large.

target scope code lines code chars stripped binary bytes
unsquinch.sh Full tool 250 4492 -
unsquinch Full tool 1075 24920 34680
squinch Full tool 2153 49952 51496
LZ4 CLI Full tool 10586 308448 272608
GNU gzip CLI Full tool 21333 371706 156040

Benchmark compression sizes

Compression size comparison Compressed size as a percentage of the original. Lower is better.

fixture Uncompressed Squinch 8K/32 Squinch 64K/128 LZ4 -1 LZ4 -12 gzip -1 gzip -9
bmp-format.bmp 71962 2839 1793 857 619 1396 635
sqlite-printf.c 54809 24714 23683 23605 18392 17705 14740
TokenType.class 3326 2163 2163 2498 2452 1841 1778
air-binary.rs 67858 27449 25168 25397 19695 19665 15742
cocoon-main.ts 10259 4034 4015 4210 3965 3054 2927
adolphe-fr.txt 184418 131303 116906 114870 78506 83420 68117
pride-and-prejudice.txt 738046 516894 452853 446060 299919 322080 264645
sqlite3 1988336 1392087 1355926 1439776 1163922 1103827 1029048

Benchmark compression speed

Compression time comparison Elapsed time for five runs in milliseconds. Lower is better.

fixture Squinch 8K/32 Squinch 64K/128 LZ4 -1 LZ4 -12 gzip -1 gzip -9
bmp-format.bmp 18 ms 23 ms 10 ms 21 ms 11 ms 15 ms
sqlite-printf.c 19 ms 28 ms 11 ms 25 ms 12 ms 27 ms
TokenType.class 10 ms 10 ms 10 ms 11 ms 12 ms 11 ms
air-binary.rs 21 ms 30 ms 11 ms 23 ms 13 ms 19 ms
cocoon-main.ts 11 ms 11 ms 10 ms 11 ms 10 ms 11 ms
adolphe-fr.txt 69 ms 171 ms 14 ms 68 ms 24 ms 61 ms
pride-and-prejudice.txt 238 ms 658 ms 30 ms 251 ms 49 ms 193 ms
sqlite3 419 ms 1124 ms 35 ms 765 ms 154 ms 941 ms

The LZ4/gzip comparisons run squinch and unsquinch with --io-buffer-size 64kiB to reduce I/O overhead without exceeding most fixtures.

Benchmark decompression speed

Decompression time comparison Elapsed time for five runs in milliseconds. Lower is better.

fixture Squinch 8K/32 Squinch 64K/128 LZ4 -1 LZ4 -12 gzip -1 gzip -9
bmp-format.bmp 10 ms 10 ms 11 ms 12 ms 10 ms 10 ms
sqlite-printf.c 11 ms 10 ms 12 ms 11 ms 11 ms 11 ms
TokenType.class 9 ms 10 ms 13 ms 12 ms 10 ms 11 ms
air-binary.rs 11 ms 11 ms 12 ms 12 ms 12 ms 12 ms
cocoon-main.ts 10 ms 10 ms 12 ms 11 ms 11 ms 10 ms
adolphe-fr.txt 15 ms 16 ms 13 ms 12 ms 16 ms 14 ms
pride-and-prejudice.txt 32 ms 32 ms 17 ms 16 ms 30 ms 27 ms
sqlite3 70 ms 71 ms 28 ms 30 ms 74 ms 67 ms

The LZ4/gzip comparisons run squinch and unsquinch with --io-buffer-size 64kiB to reduce I/O overhead without exceeding most fixtures.

Benchmark window sizes compression size

This comparison varies the Squinch window size and uses the default match limit of 128.

Each colored line represents one input fixture.

Window-size compression size comparison Compressed size as a percentage of the original. Lower is better.

fixture Uncompressed 256 bytes 4 kiB 8 kiB 32 kiB 64 kiB
bmp-format.bmp 71962 2963 1829 1817 1804 1793
sqlite-printf.c 54809 30623 25215 24599 23829 23683
TokenType.class 3326 2231 2163 2163 2163 2163
air-binary.rs 67858 38100 28383 27317 25514 25168
cocoon-main.ts 10259 4462 4113 4029 4015 4015
adolphe-fr.txt 184418 141870 135326 131120 121144 116906
pride-and-prejudice.txt 738046 570601 533180 515900 472669 452853
sqlite3 1988336 1475798 1405066 1390725 1365894 1355926

Benchmark window sizes compression time

This comparison varies the Squinch window size and uses the default match limit of 128.

Each colored line represents one input fixture.

Window-size compression time comparison Elapsed time for five runs in milliseconds. Lower is better.

fixture 256 bytes 4 kiB 8 kiB 32 kiB 64 kiB
bmp-format.bmp 17 ms 21 ms 22 ms 23 ms 23 ms
sqlite-printf.c 14 ms 19 ms 22 ms 27 ms 28 ms
TokenType.class 10 ms 10 ms 10 ms 10 ms 10 ms
air-binary.rs 15 ms 20 ms 22 ms 30 ms 30 ms
cocoon-main.ts 10 ms 11 ms 11 ms 11 ms 11 ms
adolphe-fr.txt 26 ms 56 ms 73 ms 137 ms 172 ms
pride-and-prejudice.txt 78 ms 189 ms 255 ms 496 ms 652 ms
sqlite3 197 ms 411 ms 499 ms 850 ms 1116 ms

Benchmark match limit sizes

This comparison varies the Squinch match limit and uses a 64 kiB window.

Each colored line represents one input fixture.

Match-limit compression size comparison Compressed size as a percentage of the original. Lower is better.

fixture Uncompressed 1 16 32 64 128 256 512
bmp-format.bmp 71962 2916 2732 2817 2070 1793 1780 1778
sqlite-printf.c 54809 27176 24115 23897 23721 23683 23631 23627
TokenType.class 3326 2192 2163 2163 2163 2163 2163 2163
air-binary.rs 67858 30258 25838 25460 25257 25168 25101 25075
cocoon-main.ts 10259 4182 4020 4021 4015 4015 4015 4015
adolphe-fr.txt 184418 137086 123344 120641 118629 116906 116212 116000
pride-and-prejudice.txt 738046 536614 476607 465683 457431 452853 450291 449240
sqlite3 1988336 1441136 1370234 1363330 1358756 1355926 1354372 1353716

Benchmark match limit speed

This comparison varies the Squinch match limit and uses a 64 kiB window.

Each colored line represents one input fixture.

Match-limit compression time comparison Elapsed time for five runs in milliseconds. Lower is better.

fixture 1 16 32 64 128 256 512
bmp-format.bmp 13 ms 16 ms 19 ms 18 ms 23 ms 34 ms 51 ms
sqlite-printf.c 15 ms 20 ms 22 ms 25 ms 27 ms 29 ms 30 ms
TokenType.class 10 ms 10 ms 10 ms 12 ms 11 ms 11 ms 10 ms
air-binary.rs 15 ms 21 ms 23 ms 26 ms 30 ms 32 ms 33 ms
cocoon-main.ts 11 ms 11 ms 11 ms 11 ms 11 ms 11 ms 11 ms
adolphe-fr.txt 31 ms 74 ms 101 ms 135 ms 172 ms 201 ms 220 ms
pride-and-prejudice.txt 95 ms 266 ms 366 ms 499 ms 651 ms 797 ms 892 ms
sqlite3 254 ms 560 ms 709 ms 889 ms 1113 ms 1360 ms 1600 ms

Benchmark look-ahead sizes compression size

This comparison varies the look-ahead buffer size and uses a 64 kiB window with the default match limit of 128.

Each colored line represents one input fixture.

Look-ahead compression size comparison Compressed size as a percentage of the original. Lower is better.

fixture Uncompressed 3 bytes 64 bytes 128 bytes 512 bytes 1 kiB 4 kiB 8 kiB 16 kiB 32 kiB
bmp-format.bmp 71962 48095 4462 3023 1942 1793 1778 1778 1778 1778
sqlite-printf.c 54809 43667 23777 23698 23683 23683 23683 23683 23683 23683
TokenType.class 3326 2859 2163 2163 2163 2163 2163 2163 2163 2163
air-binary.rs 67858 54773 25414 25192 25168 25168 25168 25168 25168 25168
cocoon-main.ts 10259 7935 4019 4015 4015 4015 4015 4015 4015 4015
adolphe-fr.txt 184418 155766 116911 116906 116906 116906 116906 116906 116906 116906
pride-and-prejudice.txt 738046 631584 452855 452853 452853 452853 452853 452853 452853 452853
sqlite3 1988336 1725877 1356604 1356074 1355951 1355926 1355910 1355910 1355910 1355910