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
| 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
| 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
| 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
- Squinch 8K/32: 8 kiB window, 32 match limit.
- Squinch 64K/128: 64 kiB window, 128 match limit.
| 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
- Squinch 8K/32: 8 kiB window, 32 match limit.
- Squinch 64K/128: 64 kiB window, 128 match limit.
| 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
- Squinch 8K/32: 8 kiB window, 32 match limit.
- Squinch 64K/128: 64 kiB window, 128 match limit.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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 |