Plate 24
zlib vs gzip.compress Same Level: Localhost Lab
Hands-on zlib.compress vs gzip.compress same-level (6) stdlib bake-off: real MB/s and sizes, measured on Linux localhost in this hands-on lab for SREs.
Aditya Challa4 min read
Intro — what this post promises
In-memory compress/decompress of a compressible fixture via zlib.compress / zlib.decompress vs gzip.compress / gzip.decompress at the same level (6). This lab reports MB/s and output size on Linux localhost.
It is not the multi-codec zstd/gzip/lz4 bake-off (lab 33) and not nginx gzip toggles (lab 20). Here the question is only: Python stdlib zlib vs gzip wrappers.
Related links:
- zstd vs gzip lz4 compression localhost lab
- nginx gzip on vs off localhost lab
- queue vs deque handoff localhost lab
- stringio vs list join localhost lab
- groupby vs manual localhost lab
- methodcaller vs getattr localhost lab
- hmac compare digest localhost lab
- argparse vs sys argv localhost lab
Lab honesty (1 Oct 2026 IST): Python 3.13.5. Affiliates: 0. No Docker. Level 6. Fixture = repeating JSON-ish lines (highly compressible).
Verdict up front (1 MiB): gzip.compress ~335.4 MB/s (out 3661 B); zlib.compress ~320.0 MB/s (out 3649 B); decompress gzip ~994.4 / zlib ~905.3 MB/s. Gzip adds a fixed ~12 B header/trailer overhead on this box.
Arms
| Arm | API |
|---|---|
zlib.compress(data, 6) | raw DEFLATE container |
gzip.compress(data, compresslevel=6) | gzip framing around zlib |
zlib.decompress / gzip.decompress | matching decode |
Lab topology
Script: lab-evidence/102-zlib-vs-gzip-compress/results/run_lab.py.
Lead table — 1 MiB (p50)
| Arm | MB/s | out bytes | ratio |
|---|---|---|---|
| gzip.compress | 335.4 | 3661 | 0.0035 |
| zlib.compress | 320.0 | 3649 | 0.0035 |
| gzip.decompress | 994.4 | — | — |
| zlib.decompress | 905.3 | — | — |
Gzip overhead vs zlib blob: 12 bytes (header + CRC trailer). Throughput is in the same ballpark — framing cost is tiny next to DEFLATE work.
Scale sketch (compress MB/s)
| Size | zlib | gzip | overhead B |
|---|---|---|---|
| 256 KiB | 330.3 | 343.8 | 12 |
| 1 MiB | 320.0 | 335.4 | 12 |
| 4 MiB | 306.7 | 319.9 | 12 |
What gzip adds
gzip.compress is zlib DEFLATE plus a gzip header and CRC32/ISIZE trailer. Use gzip when peers expect .gz / HTTP Content-Encoding: gzip. Use raw zlib (or raw DEFLATE) when you own both ends and want a smaller envelope (e.g. some wire protocols).
Streaming note
This lab uses one-shot compress/decompress on full buffers. Chunked compressobj / GzipFile changes memory profile and can change throughput — re-measure if your pipeline is streaming.
Reading it
- Same level ⇒ nearly identical compress rates; pick the container, not the mythical faster twin.
- Decompress is several× compress here (compressible payload).
- Tiny fixed overhead matters more on small blobs than on multi‑MiB ones.
- For codec shopping (zstd/lz4), go to lab 33 — not this post.
Level fairness
Always pin the same compresslevel (here 6, zlib/gzip default band). Comparing zlib-1 to gzip-9 is a common blog mistake and says nothing useful about framing overhead.
Wire format reminder
HTTP Content-Encoding: gzip, .gz files on disk, and many CLIs speak gzip. Some databases and custom RPCs prefer zlib or raw DEFLATE. Matching the peer’s expected magic bytes matters more than the ~tens of MB/s delta on this box.
Pitfalls
- Comparing zlib level 6 to gzip level 9 (unfair).
- Forgetting gzip framing when a client expects zlib-only (or vice versa).
- Using this highly repetitive fixture as a ratio benchmark for “typical” traffic.
- Conflating Python API speed with nginx gzip filter cost (lab 20).
Reproduce
Evidence: summary.json, summary.txt.
Limits
One Linux box. Synthetic repeating JSON lines (very compressible). Level fixed at 6. Not streaming zlib.compressobj / GzipFile chunked APIs.
Takeaway
At 1 MiB level 6, gzip.compress ~335.4 MB/s and zlib.compress ~320.0 MB/s — choose gzip for interoperability, zlib for a leaner envelope (+12 B for gzip here).
Lab evidence
What I found running this
Lab 1 Oct 2026 IST. Python 3.13.5. level=6. 1MiB: gzip_compress 335.4 MB/s out=3661; zlib_compress 320.0 out=3649; overhead 12B. Not lab 33 multi-codec / lab 20 nginx. Affiliates: 0. Evidence: lab-evidence/102-zlib-vs-gzip-compress/.
Related links
Plate 88
mmap Write vs pwrite Region: Localhost Lab
Hands-on mmap MAP_SHARED write+msync vs pwrite region update: real MB/s with durability labels, measured on Linux localhost in this hands-on lab for SREs.
Observability & SRE · 1 Oct 2026
Plate 12
islice vs list Slice Windows: Localhost Lab
Hands-on itertools.islice vs list slice window lab: real ops/s taking ranges from sequences, measured on Linux localhost in this hands-on lab for SREs.
Observability & SRE · 1 Oct 2026
Plate 07
heapq.merge vs sorted(chain): Localhost Lab
Hands-on heapq.merge vs sorted(chain) multi-way merge: real records/s on pre-sorted lists, measured on Linux localhost today in this hands-on lab for SREs.
Observability & SRE · 1 Oct 2026