gzip vs bzip2 vs xz: Differences and When to Use Each
gzip vs bzip2 vs xz compared: algorithms, speed, ratio, memory, multi-threading, tar flags, commands, and which to use for logs, backups and releases.
gzip, bzip2 and xz are lossless compressors with different trade-offs. gzip (DEFLATE) is the fastest and most compatible. bzip2 (Burrows-Wheeler) compresses text better but is slow, especially to decompress. xz (LZMA2) gives the smallest files and decompresses quickly, but compressing at high levels costs a lot of CPU time and memory.
This guide explains how the three formats differ, which commands and flags matter, and how to pick one for logs, backups, releases and pipelines. It is part of our Linux and RHEL 10 guide. Defaults and memory figures come from the current gzip manual and the xz and bzip2 man pages, checked in November 2026.
Key takeaways
- Use gzip when speed and compatibility matter more than size: log rotation, HTTP responses, quick transfers.
- Use xz when the file is compressed once and downloaded or stored many times: release tarballs, archives, images.
- bzip2 rarely wins today. xz usually produces smaller files and decompresses faster, but bzip2 can still recover undamaged blocks from a corrupted file.
- xz has built-in multi-threading (
-T), and since xz 5.6 it uses all CPU threads by default. gzip and bzip2 are single-threaded; use pigz or pbzip2/lbzip2 for parallel work. - High xz presets need far more memory:
xz -9uses about 674 MiB to compress and 65 MiB to decompress. - None of these formats archive directories by themselves. Combine them with
tar(-z,-j,-J).
gzip vs bzip2 vs xz at a glance
| Property | gzip | bzip2 | xz |
|---|---|---|---|
| Algorithm | DEFLATE (LZ77 plus Huffman coding) | Burrows-Wheeler block sorting plus Huffman coding | LZMA2 in the .xz container |
| File extension | .gz, .tgz | .bz2, .tbz2 | .xz, .txz |
| GNU tar flag | -z | -j | -J |
| Levels and default | 1 to 9, default 6 | Block size 100k to 900k (-1 to -9), default 900k | Presets 0 to 9, default 6, plus -e (extreme) |
| Compression speed | Fast | Slow | Slow at high presets, moderate at low ones |
| Decompression speed | Fastest | Slowest of the three | Fast |
| Typical size | Largest | Smaller than gzip | Usually smallest |
| Memory (default level) | Very small | About 7.6 MB to compress, 3.7 MB to decompress (from the man page formula) | 94 MiB to compress, 9 MiB to decompress at -6 |
| Built-in multi-threading | No (pigz is a parallel drop-in) | No (pbzip2, lbzip2) | Yes, -T; default is all threads since 5.6 |
| Specification | RFC 1952 (format), RFC 1951 (DEFLATE) | No formal standard | .xz file format specification from the Tukaani project |
| Damage recovery | Limited | bzip2recover salvages intact blocks | Limited; integrity check (CRC64 by default) detects damage |
Exact speed and ratio depend heavily on the data. Text, logs and source code compress very well with all three. Files that are already compressed (JPEG, MP4, most container image layers, other archives) barely shrink, and spending CPU on them is wasted. If you need numbers for your own data, use the benchmark script later in this guide.
How each format works
gzip: DEFLATE and a header with a CRC
gzip finds repeated strings with LZ77 and replaces them with back-references, then Huffman-codes the result. The format is defined in RFC 1952 and the DEFLATE stream in RFC 1951, which is why gzip data appears everywhere: HTTP Content-Encoding: gzip, PNG and ZIP use DEFLATE, and nearly every language has a library for it. The small 32 KB search window keeps gzip fast and light on memory, but it cannot exploit repeats that are far apart.
bzip2: block sorting
bzip2 splits input into blocks of 100k to 900k, applies the Burrows-Wheeler transform to group similar characters, then uses move-to-front and Huffman coding. Larger blocks compress better and use more memory. The man page gives the memory cost as 400k + 8 x block size to compress and 100k + 4 x block size to decompress (or 2.5 x block size with -s). Because each block is independent, bzip2recover can pull good blocks out of a damaged file.
xz: LZMA2 with large dictionaries
xz uses LZMA2 with a dictionary from 256 KiB (preset 0) up to 64 MiB (preset 9). A large dictionary lets it find repeats across a big archive, which is where most of its gain over gzip comes from. Decompression mostly copies bytes from the dictionary, so it stays fast even when compression was slow. The .xz container adds an integrity check (CRC64 by default) and supports independent blocks, which is what makes multi-threaded compression and decompression possible.
Everyday commands
The three tools share most options, so learning one teaches you the others.
| Task | gzip | bzip2 | xz |
|---|---|---|---|
| Compress (replaces the file) | gzip file | bzip2 file | xz file |
| Keep the original | gzip -k file | bzip2 -k file | xz -k file |
| Decompress | gunzip file.gz or gzip -d | bunzip2 file.bz2 or bzip2 -d | unxz file.xz or xz -d |
| Print to stdout | zcat, gzip -dc | bzcat, bzip2 -dc | xzcat, xz -dc |
| Test integrity | gzip -t | bzip2 -t | xz -t |
| Show sizes and ratio | gzip -l | Not available | xz -l |
| Fastest / best | -1 / -9 | -1 / -9 (block size) | -0 / -9e |
| Search inside | zgrep | bzgrep | xzgrep |
# compress a log, keep the original, show the result
gzip -k -9 app.log
gzip -l app.log.gz
# xz with all CPU threads and the extreme variant of preset 6
xz -k -T0 -6e dump.sql
xz -l dump.sql.xz
# stream: compress command output without a temp file
journalctl -b | xz -T0 > boot-journal.xz
xzcat boot-journal.xz | grep -i error
Two gzip options are worth knowing for operations work. --rsyncable resets the compressor periodically so rsync can find unchanged regions, at a cost of about 1% in size according to the gzip manual. -r compresses every file inside a directory tree individually, which is different from creating one archive.
Using compression with tar
gzip, bzip2 and xz compress a single stream. To bundle a directory, create a tar archive and compress it in the same step:
tar -czf site-backup.tar.gz /var/www/html # gzip
tar -cjf site-backup.tar.bz2 /var/www/html # bzip2
tar -cJf site-backup.tar.xz /var/www/html # xz
# let tar choose the compressor from the file suffix
tar -caf site-backup.tar.xz /var/www/html
# pass options to the compressor
tar -I 'xz -T0 -9' -cf big.tar.xz /data
XZ_OPT='-T0 -6' tar -cJf big.tar.xz /data
# list before extracting, then extract (GNU tar detects the format when reading)
tar -tvf site-backup.tar.xz
tar -xf site-backup.tar.xz -C /restore
For permissions, ownership, exclusions and encrypting archives, see our guide to creating secure archives with tar and gzip.
Multi-threading and memory limits
Compression speed on a modern server is mostly a question of how many cores you can use.
- xz splits the input into blocks and compresses them in parallel. The xz man page says the default for
-Tis 0 (use as many threads as there are processors); in 5.4.x and older it was 1.-T1forces single-threaded mode. Multi-threaded output is not byte-identical to single-threaded output, and only files written in multi-threaded mode can be decompressed with multiple threads. - gzip has no threading. pigz writes standard gzip files using several cores.
- bzip2 has no threading. pbzip2 and lbzip2 produce compatible
.bz2files in parallel.
On RHEL, check whether pigz or lbzip2 is in your enabled repositories with dnf info pigz; if not, EPEL usually carries them.
Memory matters most with xz, because each preset raises the dictionary size. These figures are from the xz man page (per thread when compressing in parallel):
| xz preset | Dictionary | Compression memory | Decompression memory |
|---|---|---|---|
-0 | 256 KiB | 3 MiB | 1 MiB |
-1 | 1 MiB | 9 MiB | 2 MiB |
-3 | 4 MiB | 32 MiB | 5 MiB |
-6 (default) | 8 MiB | 94 MiB | 9 MiB |
-9 | 64 MiB | 674 MiB | 65 MiB |
Running xz -T0 -9 on a 32-core build agent can therefore try to use many gigabytes. Cap it with --memlimit-compress=2GiB, and xz will reduce the thread count to fit. On small containers or embedded targets, remember that whoever decompresses a -9 file needs 65 MiB free.
Which format should you use?
| Use case | Good choice | Why |
|---|---|---|
| Rotated application and system logs | gzip | Fast, low CPU on busy servers, readable with zcat/zgrep everywhere; logrotate compresses with gzip unless you change compresscmd |
| Nightly backups to disk or object storage | xz -T0 at a low or default preset, or gzip if the backup window is tight | Smaller files reduce storage and transfer; test restore speed too |
| Software release tarballs | xz (often published next to a .tar.gz) | Compressed once, downloaded many times, so the smallest file wins |
| HTTP responses | gzip (or Brotli/zstd where clients support them) | Every browser and HTTP client understands gzip |
| Moving data between hosts right now | gzip or pigz | Compression time is part of the transfer time |
| Archives that may be partly corrupted | bzip2 | bzip2recover can extract intact blocks |
| Sharing with Windows or very old systems | gzip (or ZIP) | Widest tool support |
Backups are about restores as much as size. Our guides to automating backups with rsync and cron and the RHEL 10 backup and restore guide show where compression fits in a full backup plan.
Where zstd fits
Zstandard (zstd) is not one of the three formats in the title, but you will meet it in modern Linux and container tooling, so it belongs in the decision. It aims for gzip-like or better speed with ratios closer to xz. Levels run from 1 to 19 (default 3), with --ultra unlocking levels up to 22, and -T0 uses all cores. GNU tar supports it with --zstd, and the OCI image specification defines a zstd media type for container layers.
tar --zstd -cf logs.tar.zst /var/log/app
zstd -T0 -19 dump.sql
zstd -d dump.sql.zst
If both ends of a pipeline are under your control, zstd is often the best default for new work. For files you publish to unknown users, gzip and xz are still the safest choices.
Security and integrity notes
- Check archives before you extract them. List contents with
tar -tvfand look for absolute paths or../entries. Do not extract untrusted archives as root. - Watch for decompression bombs. A tiny file can expand to fill a disk. Extract into a quota-limited directory or container, and use
xz --memlimit-decompressto cap memory. - Integrity is not authenticity. The CRC in each format detects accidental corruption only. Verify downloads with published SHA-256 checksums and GPG signatures.
- Keep XZ Utils patched. In March 2024 a backdoor was found in the upstream release tarballs of XZ Utils 5.6.0 and 5.6.1 (CVE-2024-3094). Red Hat stated that RHEL was not affected; affected packages reached Fedora development releases and Debian unstable. The 5.6.2 release removed the code. Run
xz --versionand update through your distribution's normal channel.
Benchmark the formats on your own data
Published benchmarks use kernel trees or text corpora that may look nothing like your files. This script compresses one sample with each tool and prints time and size. Run it on a copy of real data, such as a day of logs or a database dump.
#!/usr/bin/env bash
# usage: ./compare.sh sample-file
set -euo pipefail
f="$1"
printf '%-12s %10s %10s\n' tool seconds bytes
printf '%-12s %10s %10s\n' original - "$(stat -c %s "$f")"
for cmd in "gzip -6" "gzip -9" "bzip2 -9" "xz -1 -T0" "xz -6 -T0" "xz -9 -T0"; do
start=$(date +%s.%N)
$cmd -c "$f" > /tmp/sample.out
end=$(date +%s.%N)
printf '%-12s %10.2f %10s\n' "$cmd" "$(echo "$end - $start" | bc)" "$(stat -c %s /tmp/sample.out)"
done
rm -f /tmp/sample.out
Also time decompression (-dc to /dev/null), because a format that is slow to restore can hurt more than one that is slow to create. Install bc first if your minimal system lacks it.
Frequently asked questions
Which is better, gzip, bzip2 or xz?
No single one wins everywhere. gzip is fastest and most compatible, xz gives the smallest files and fast decompression, and bzip2 sits between them on size but is slowest to decompress. Choose by whether speed, size or compatibility matters most for the job.
Is xz always smaller than gzip?
For typical text, logs and source code, yes, usually by a clear margin. For data that is already compressed, such as images, video or archives, all three give little or no gain and may even add a few bytes.
Why is bzip2 still used?
Mostly for compatibility with existing archives and scripts. It also has bzip2recover, which can salvage intact blocks from a damaged file. For new archives, xz or zstd is usually a better fit.
How do I extract .tar.gz, .tar.bz2 and .tar.xz files?
Use tar -xf archive.tar.gz (or .bz2, .xz). GNU tar detects the compression when reading, so you do not need -z, -j or -J for extraction. Add -C /path to extract somewhere else.
Does gzip support multiple CPU cores?
No. The standard gzip tool is single-threaded. pigz produces standard gzip output using several cores, and xz and zstd have threading built in with -T.
What compression level should I use?
Start with the default (gzip 6, xz 6). Go lower when CPU time or latency matters, and higher only for files that are compressed once and stored or downloaded many times. Above the defaults, gains are small and time grows quickly.
Is xz safe to use after the 2024 backdoor?
Yes, on patched systems. The malicious code was only in upstream 5.6.0 and 5.6.1 release tarballs, Red Hat stated RHEL was not affected, and 5.6.2 removed it. Keep xz updated through your distribution like any other package.
Can I use these formats for log rotation?
Yes. logrotate compresses rotated files with gzip by default when compress is set. You can switch to xz with compresscmd /usr/bin/xz and compressext .xz, which saves space at the cost of more CPU during rotation.
Learn more
Compression is one of the everyday skills covered in our Linux administration training, along with tar, backups and storage. For the commands you will use alongside these tools, see 20 Linux commands for DevOps engineers and RHEL 10 basic commands.
References
- GNU gzip manual
- RFC 1952: GZIP file format specification
- RFC 1951: DEFLATE compressed data format
- bzip2(1) manual page
- xz(1) manual page
- XZ Utils project page
- GNU tar manual: creating and reading compressed archives
- Zstandard project
- Red Hat: CVE-2024-3094
- CISA alert on XZ Utils (CVE-2024-3094)
- Tukaani: XZ Utils backdoor
What's Your Reaction?
Like
0
Dislike
0
Love
0
Funny
0
Angry
0
Sad
0
Wow
0