Skip to content

Gzip

Gzip is the most widely supported compression format, used everywhere from HTTP to file archives. It provides good compression with universal compatibility.

PropertyValue
StandardRFC 1952
First Release1992
ImplementationVendored zlib 1.3.1
Licensezlib
LevelCompressDecompressRatio
fast2.4 GB/s2.4 GB/s99.2%
default723 MB/s2.8 GB/s99.6%
best691 MB/s2.9 GB/s99.6%
  • ✅ Universal compatibility
  • ✅ Streaming support
  • ✅ CRC32 checksum
  • ✅ Auto-detection (magic bytes)
  • ✅ Multiple compression levels
  • ❌ No dictionary support
const cz = @import("compressionz");
// Compress
const compressed = try cz.compress(.gzip, data, allocator);
defer allocator.free(compressed);
// Decompress
const decompressed = try cz.decompress(.gzip, compressed, allocator);
defer allocator.free(decompressed);
// Fast compression (2.4 GB/s)
const fast = try cz.compressWithOptions(.gzip, data, allocator, .{
.level = .fast,
});
// Default (balanced)
const default = try cz.compressWithOptions(.gzip, data, allocator, .{
.level = .default,
});
// Best compression
const best = try cz.compressWithOptions(.gzip, data, allocator, .{
.level = .best,
});
LevelSpeedRatioUse Case
fastestFastestLowerReal-time HTTP
fastFastGoodDynamic content
defaultModerateBetterGeneral use
betterSlowerBetterPre-compression
bestSlowestBestStatic files

Gzip excels at streaming large files:

const cz = @import("compressionz");
const std = @import("std");
pub fn compressFile(allocator: std.mem.Allocator, input_path: []const u8, output_path: []const u8) !void {
const input = try std.fs.cwd().openFile(input_path, .{});
defer input.close();
const output = try std.fs.cwd().createFile(output_path, .{});
defer output.close();
var comp = try cz.compressor(.gzip, allocator, output.writer(), .{
.level = .default,
});
defer comp.deinit();
var buf: [65536]u8 = undefined;
while (true) {
const n = try input.read(&buf);
if (n == 0) break;
try comp.writer().writeAll(buf[0..n]);
}
try comp.finish();
}
pub fn decompressFile(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
var decomp = try cz.decompressor(.gzip, allocator, file.reader());
defer decomp.deinit();
return decomp.reader().readAllAlloc(allocator, 1024 * 1024 * 1024);
}

Protect against decompression bombs:

const safe = try cz.decompressWithOptions(.gzip, untrusted_data, allocator, .{
.max_output_size = 100 * 1024 * 1024, // 100 MB limit
});
const cz = @import("compressionz");
// Compress with level
const compressed = try cz.gzip.compress(data, allocator, .default);
defer allocator.free(compressed);
// Decompress
const decompressed = try cz.gzip.decompress(compressed, allocator);
defer allocator.free(decompressed);
// With size limit
const limited = try cz.gzip.decompressWithLimit(compressed, allocator, max_size);
┌─────────────────────────────────────────────────────┐
│ Header (10+ bytes) │
│ - Magic: 0x1f 0x8b │
│ - Compression method: 0x08 (deflate) │
│ - Flags (1 byte) │
│ - Modification time (4 bytes) │
│ - Extra flags (1 byte) │
│ - OS (1 byte) │
│ - [Extra field] (if FEXTRA) │
│ - [Original filename] (if FNAME) │
│ - [Comment] (if FCOMMENT) │
│ - [CRC16] (if FHCRC) │
├─────────────────────────────────────────────────────┤
│ Compressed Data (deflate) │
├─────────────────────────────────────────────────────┤
│ Trailer (8 bytes) │
│ - CRC32 of uncompressed data (4 bytes) │
│ - Original size mod 2^32 (4 bytes) │
└─────────────────────────────────────────────────────┘
// Gzip magic number
const GZIP_MAGIC: [2]u8 = .{ 0x1f, 0x8b };
// Detection
if (data.len >= 2 and data[0] == 0x1f and data[1] == 0x8b) {
// It's Gzip
}

Gzip uses DEFLATE compression:

  1. LZ77 — Find repeated sequences, encode as (length, distance) pairs
  2. Huffman coding — Variable-length codes for symbols
  3. Dynamic trees — Optimal Huffman trees per block
  • 30+ years of support
  • Built into HTTP (Content-Encoding)
  • Native OS support (Linux, macOS, Windows)
  • Every programming language has a library
  • Standard for .gz files

Gzip is the standard for HTTP content encoding:

pub fn handleRequest(allocator: Allocator, request: *Request, response: *Response) !void {
const accept_encoding = request.headers.get("Accept-Encoding") orelse "";
if (std.mem.indexOf(u8, accept_encoding, "gzip") != null) {
const body = getResponseBody();
const compressed = try cz.compress(.gzip, body, allocator);
defer allocator.free(compressed);
response.headers.set("Content-Encoding", "gzip");
try response.send(compressed);
} else {
try response.send(getResponseBody());
}
}
pub fn compressLogs(allocator: Allocator, log_dir: []const u8) !void {
var dir = try std.fs.cwd().openDir(log_dir, .{ .iterate = true });
defer dir.close();
var iter = dir.iterate();
while (try iter.next()) |entry| {
if (std.mem.endsWith(u8, entry.name, ".log")) {
const input_path = try std.fs.path.join(allocator, &.{ log_dir, entry.name });
defer allocator.free(input_path);
const output_path = try std.fmt.allocPrint(allocator, "{s}.gz", .{input_path});
defer allocator.free(output_path);
try compressFile(allocator, input_path, output_path);
}
}
}
MetricGzipZstdBrotli
Compress2.4 GB/s12 GB/s1.3 GB/s
Decompress2.4 GB/s11.6 GB/s1.9 GB/s
Ratio99.2%99.9%99.9%
HTTP SupportUniversalGrowingGood
Browser Support100%Some~95%

Use Gzip when:

  • Maximum compatibility needed
  • HTTP Content-Encoding for all browsers
  • Interoperating with Unix tools
  • Working with .gz files

Consider alternatives when:

  • Speed matters (use Zstd or LZ4)
  • Static web assets (use Brotli)
  • Best compression needed (use Zstd/Brotli)

Gzip decompression requires a sliding window buffer:

ContextCompression MemoryDecompression Memory
Gzip~256 KB~32 KB
Per-stream~256 KB~32 KB

For memory-constrained environments, be aware of the per-stream overhead.

const result = cz.decompress(.gzip, data, allocator) catch |err| switch (err) {
error.InvalidData => {
// Not valid gzip data, or corrupted
},
error.ChecksumMismatch => {
// CRC32 verification failed
},
error.UnexpectedEof => {
// Truncated gzip data
},
else => return err,
};