Gzip
Gzip is the most widely supported compression format, used everywhere from HTTP to file archives. It provides good compression with universal compatibility.
At a Glance
Section titled “At a Glance”| Property | Value |
|---|---|
| Standard | RFC 1952 |
| First Release | 1992 |
| Implementation | Vendored zlib 1.3.1 |
| License | zlib |
Performance
Section titled “Performance”| Level | Compress | Decompress | Ratio |
|---|---|---|---|
| fast | 2.4 GB/s | 2.4 GB/s | 99.2% |
| default | 723 MB/s | 2.8 GB/s | 99.6% |
| best | 691 MB/s | 2.9 GB/s | 99.6% |
Features
Section titled “Features”- ✅ Universal compatibility
- ✅ Streaming support
- ✅ CRC32 checksum
- ✅ Auto-detection (magic bytes)
- ✅ Multiple compression levels
- ❌ No dictionary support
Basic Usage
Section titled “Basic Usage”const cz = @import("compressionz");
// Compressconst compressed = try cz.compress(.gzip, data, allocator);defer allocator.free(compressed);
// Decompressconst decompressed = try cz.decompress(.gzip, compressed, allocator);defer allocator.free(decompressed);Compression Levels
Section titled “Compression Levels”// 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 compressionconst best = try cz.compressWithOptions(.gzip, data, allocator, .{ .level = .best,});Level Comparison
Section titled “Level Comparison”| Level | Speed | Ratio | Use Case |
|---|---|---|---|
fastest | Fastest | Lower | Real-time HTTP |
fast | Fast | Good | Dynamic content |
default | Moderate | Better | General use |
better | Slower | Better | Pre-compression |
best | Slowest | Best | Static files |
Streaming
Section titled “Streaming”Gzip excels at streaming large files:
Streaming Compression
Section titled “Streaming Compression”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();}Streaming Decompression
Section titled “Streaming Decompression”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);}Decompression Safety
Section titled “Decompression Safety”Protect against decompression bombs:
const safe = try cz.decompressWithOptions(.gzip, untrusted_data, allocator, .{ .max_output_size = 100 * 1024 * 1024, // 100 MB limit});Direct API Access
Section titled “Direct API Access”const cz = @import("compressionz");
// Compress with levelconst compressed = try cz.gzip.compress(data, allocator, .default);defer allocator.free(compressed);
// Decompressconst decompressed = try cz.gzip.decompress(compressed, allocator);defer allocator.free(decompressed);
// With size limitconst limited = try cz.gzip.decompressWithLimit(compressed, allocator, max_size);Format Details
Section titled “Format Details”Gzip Structure
Section titled “Gzip Structure”┌─────────────────────────────────────────────────────┐│ 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) │└─────────────────────────────────────────────────────┘Magic Bytes
Section titled “Magic Bytes”// Gzip magic numberconst GZIP_MAGIC: [2]u8 = .{ 0x1f, 0x8b };
// Detectionif (data.len >= 2 and data[0] == 0x1f and data[1] == 0x8b) { // It's Gzip}Algorithm Details
Section titled “Algorithm Details”Gzip uses DEFLATE compression:
- LZ77 — Find repeated sequences, encode as (length, distance) pairs
- Huffman coding — Variable-length codes for symbols
- Dynamic trees — Optimal Huffman trees per block
Why Gzip is Universal
Section titled “Why Gzip is Universal”- 30+ years of support
- Built into HTTP (Content-Encoding)
- Native OS support (Linux, macOS, Windows)
- Every programming language has a library
- Standard for
.gzfiles
Use Cases
Section titled “Use Cases”HTTP Compression
Section titled “HTTP Compression”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()); }}File Compression
Section titled “File Compression”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); } }}Gzip vs Alternatives
Section titled “Gzip vs Alternatives”| Metric | Gzip | Zstd | Brotli |
|---|---|---|---|
| Compress | 2.4 GB/s | 12 GB/s | 1.3 GB/s |
| Decompress | 2.4 GB/s | 11.6 GB/s | 1.9 GB/s |
| Ratio | 99.2% | 99.9% | 99.9% |
| HTTP Support | Universal | Growing | Good |
| Browser Support | 100% | Some | ~95% |
When to Use Gzip
Section titled “When to Use Gzip”Use Gzip when:
- Maximum compatibility needed
- HTTP Content-Encoding for all browsers
- Interoperating with Unix tools
- Working with
.gzfiles
Consider alternatives when:
- Speed matters (use Zstd or LZ4)
- Static web assets (use Brotli)
- Best compression needed (use Zstd/Brotli)
Memory Considerations
Section titled “Memory Considerations”Gzip decompression requires a sliding window buffer:
| Context | Compression Memory | Decompression Memory |
|---|---|---|
| Gzip | ~256 KB | ~32 KB |
| Per-stream | ~256 KB | ~32 KB |
For memory-constrained environments, be aware of the per-stream overhead.
Error Handling
Section titled “Error Handling”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,};