Name
Deflate::Faster - High-speed DEFLATE, zlib, and gzip compression and decompression using libdeflate
Synopsis
# High-performance drop-in replacement for Gzip::Faster
use Deflate::Faster qw(gzip gunzip);
my $compressed = gzip($data);
my $decompressed = gunzip($compressed);
# Optional compression level (0 = uncompressed, 1 = fastest, 6 = default, 12 = maximum)
my $fast_gz = gzip($data, 1);
# Raw DEFLATE and zlib formats
use Deflate::Faster qw(deflate inflate deflate_raw inflate_raw);
my $zlib_stream = deflate($data);
my $original = inflate($zlib_stream);
my $raw_stream = deflate_raw($data);
my $unraw = inflate_raw($raw_stream);
# File operations
use Deflate::Faster qw(gzip_file gunzip_file gzip_to_file gunzip_to_file);
gzip_to_file($data, 'output.gz');
my $content = gunzip_file('output.gz');
# Object-oriented interface with metadata and safety limits
my $df = Deflate::Faster->new();
$df->level(1);
$df->copy_perl_flags(1); # Preserve Perl UTF-8 flag
$df->max_size(10 * 1024*1024); # Guard against decompression bombs
my $out = $df->zip($data);
my $in = $df->unzip($out);
Description
Deflate::Faster provides ultra-fast in-memory and file compression and decompression for the DEFLATE, zlib, and gzip formats. It is designed as a high-performance alternative and drop-in upgrade for Gzip::Faster.
Under the hood, Deflate::Faster is powered by libdeflate (by Eric Biggers), a whole-buffer DEFLATE engine designed for high throughput. libdeflate utilizes modern CPU SIMD instructions: (V)PCLMULQDQ for hardware-accelerated CRC-32, AVX2 and AVX-VNNI for Adler-32, and an optimized scalar core with BMI2 instructions on x86_64, as well as ARM NEON and PMULL on AArch64.
Key features:
High Throughput: Typically 1.5x to 4x faster than standard zlib and
Gzip::Fasteracross a wide variety of payloads.Thread-local Engine Caching: Compressor and decompressor C contexts are cached in thread-local storage (TLS), eliminating per-call allocator overhead and heap churn while remaining fully thread-safe.
Direct Buffer Sizing: Compresses and decompresses directly into Perl scalar buffers, automatically shrinking output buffers to eliminate excess heap memory retention.
Drop-in API Compatibility: Provides drop-in compatible functions and methods matching Gzip::Faster.
Full Multi-member Gzip Support: Transparently decompresses concatenated gzip streams (such as BGZF files or concatenated logs) while strictly rejecting corrupted trailers and trailing garbage.
Extended Compression Levels: Supports levels
0(uncompressed/stored) through12(maximum compression), with level6as default.
Functions
gzip
my $zipped = gzip($plain, [$level]);
Compresses $plain data into the standard gzip format (RFC 1952). An optional $level between 0 and 12 may be supplied (defaults to 6). $level = -1 or undef selects the default level.
Returns undef with a warning if $plain is undefined or empty.
gunzip
my $plain = gunzip($zipped);
Decompresses $zipped gzip data into the original plain text or binary scalar. Transparently decompresses multi-member gzip streams (concatenated gzip members). Also auto-detects and decompresses zlib streams (RFC 1950) if passed.
Returns undef with a warning if $zipped is undefined or empty. Croaks if the input is corrupt, truncated, or followed by trailing garbage.
deflate
my $deflated = deflate($plain, [$level]);
Compresses $plain into the zlib container format (RFC 1950, with zlib header and Adler-32 trailer).
inflate
my $plain = inflate($deflated);
Decompresses $deflated zlib stream. Croaks if input is invalid or contains trailing bytes.
deflate_raw
my $raw = deflate_raw($plain, [$level]);
Compresses $plain into raw DEFLATE format (RFC 1951, without container headers or checksum trailers).
inflate_raw
my $plain = inflate_raw($raw);
Decompresses raw DEFLATE data. Croaks if input is invalid or contains trailing bytes.
gzip_file
my $zipped = gzip_file($file, %options);
Reads $file and returns its gzip-compressed content. Supported options:
level: Compression level (0..12).file_name: Custom filename recorded in the gzip header (defaults to the path of$file).mod_time: Custom modification timestamp recorded in the gzip header (defaults to the file'smtime).copy_perl_flags: Preserves Perl's internal UTF-8 flag.
gunzip_file
my $plain = gunzip_file($file, %options);
Reads and decompresses gzip file $file. Supported options:
max_size: Maximum allowed uncompressed size in bytes.copy_perl_flags: Restores Perl's UTF-8 flag if present in the header and the data is valid UTF-8.file_name: Scalar reference (e.g.file_name => \$name) to receive the filename from the header.mod_time: Scalar reference (e.g.mod_time => \$mtime) to receive the modification timestamp.
gzip_to_file
gzip_to_file($plain, $file, %options);
Compresses $plain and writes the result directly to $file using unbuffered system I/O. Accepts the same options as "gzip_file".
gunzip_to_file
gunzip_to_file($zipped, $file, %options);
Decompresses $zipped and writes the plain data directly to $file. Accepts max_size. Always writes raw binary bytes to the destination file.
Methods (Object-Oriented)
new
my $df = Deflate::Faster->new();
Creates a new compression/decompression object. Subclasses correctly inherit and receive objects blessed into their respective class.
zip
my $zipped = $df->zip($plain);
Compresses data using the object's configured parameters. Note that if a file_name was set on the object, it is written to the header and then cleared from the object, matching Gzip::Faster.
unzip
my $plain = $df->unzip($zipped);
Decompresses data using the object's configured parameters. Clears any previous file_name and mod_time before decompression and populates them if present in the decompressed stream.
level
$df->level($level);
Sets compression level (0..12, default 6). Values -1 or undef reset to the default level. Out-of-range values warn and are clamped.
raw
$df->raw(1);
Enables (1) or disables (0) raw DEFLATE format (RFC 1951).
gzip_format
$df->gzip_format(1);
Enables (1) or disables (0) gzip format (RFC 1952).
max_size
$df->max_size(1024 * 1024);
Sets the maximum allowed decompression size in bytes to prevent decompression bomb attacks. An undefined value (undef), zero (0), negative integers, or values below 1 (such as fractional values like 0.5) indicate unlimited decompression (the default). Strings with numeric prefixes and suffixes (such as "10MB" or "1_000") undergo standard Perl integer conversion, limiting to their integer prefix (e.g. 10 or 1 byte) with a warning under use warnings. Strings with no numeric prefix (such as "none" or "abc") evaluate to 0 and select unlimited decompression (also with a warning). If decompression output exceeds the configured limit, decompression croaks without allocating excess memory.
On gzip streams with a plausible uncompressed size (ISIZE) exceeding the initial 64 MB allocation buffer, the buffer expands exponentially up to eight times (8x) the data already verified and decompressed in earlier passes. For complete protection against excessive memory consumption or decompression bombs, configure an explicit max_size.
file_name
$df->file_name("archive.tar");
my $name = $df->file_name();
Sets or gets the filename field in the gzip header. Returns an independent scalar copy. Embedded NUL bytes are safely truncated at the first NUL.
mod_time
$df->mod_time(time());
my $mtime = $df->mod_time();
Sets or gets the modification timestamp in the gzip header. Returns an independent scalar copy.
copy_perl_flags
$df->copy_perl_flags(1);
When enabled (1), zip records Perl's internal UTF-8 flag in an extra header field (GF\1\0). Upon decompression, unzip inspects this field and, if valid UTF-8, restores the UTF-8 flag on the resulting string.
Differences from Gzip::Faster
While Deflate::Faster provides drop-in API compatibility with Gzip::Faster, there are several intentional improvements and behavioral differences:
Multi-member Gzip Streams:
Deflate::Fasterautomatically decompresses multi-member gzip files (such as concatenated.gzfiles or BGZF format). Gzip::Faster croaks with "Zlib did not finish processing the string".Trailing Garbage and Padding:
Deflate::Fasterstrictly rejects invalid trailing bytes (including trailing NUL padding or garbage) following a valid stream, croaking with an error.Compression Level Defaults:
level(undef)andlevel(-1)select the default level (level 6). Out-of-range negative levels clamp to the default with a warning.Metadata Getters and State: Calling
$df->file_name(undef)or$df->mod_time(undef)acts as a getter returningundefwithout overwriting previously configured metadata.OS Header Field: In custom gzip headers,
Deflate::Fasterwrites OS byte0xff(unknown/unspecified OS per RFC 1952), whereas Gzip::Faster writes0x03(Unix) or0x00.Error Messages: Exception strings from
Deflate::Fasteruse consistent, clean diagnostics (such as "Data input to inflate is not in libz format") rather than zlib numerical error codes.Subclassing: Calling
Subclass->newreturns an object blessed intoSubclass, whereas Gzip::Faster hardcoded blessing intoGzip::Faster.Extended Compression Levels: Supports levels
0through12, whereas Gzip::Faster supports0through9.
Diagnostics
Attempt to compress empty string-
(W) The input passed to
gzip,deflate, ordeflate_rawwas defined but empty (0 bytes).undefis returned. Attempt to uncompress empty string-
(W) The input passed to
gunzip,inflate, orinflate_rawwas defined but empty.undefis returned. Empty input-
(W) The input scalar passed to compression or decompression was undefined (
undef).undefis returned. Data input to inflate is not in libz format-
(F) The input data was not a valid gzip, zlib, or raw DEFLATE stream, or was truncated, or contained invalid trailing garbage.
Uncompressed data exceeds max_size of %d bytes-
(F) Decompressed output exceeded the limit set by "max_size".
Cannot set compression level to less than 0-
(W) The requested compression level was negative (other than -1) and was clamped to 0.
Cannot set compression level to more than 12-
(W) The requested compression level exceeded 12 and was clamped to 12.
Benchmarks
Comparative benchmark against Gzip::Faster on Linux x86_64:
Payload: Small string (72 bytes, alternating 8 diverse payloads)
Compression:
Gzip::Faster: 31,355 ops/s
Deflate::Faster (lvl 6): 180,551 ops/s (+476% / 5.8x faster)
Deflate::Faster (lvl 1): 224,438 ops/s (+616% / 7.2x faster)
Decompression:
Deflate::Faster: 1,410,301 ops/s
Gzip::Faster: 1,458,101 ops/s (comparable throughput on tiny payloads)
Roundtrip:
Gzip::Faster: 28,395 ops/s
Deflate::Faster (lvl 6): 158,553 ops/s (+458% / 5.6x faster)
Payload: Medium text (2 KB, alternating 8 diverse payloads)
Compression:
Gzip::Faster: 18,793 ops/s
Deflate::Faster (lvl 6): 67,995 ops/s (+262% / 3.6x faster)
Deflate::Faster (lvl 1): 120,849 ops/s (+543% / 6.4x faster)
Decompression:
Gzip::Faster: 239,253 ops/s
Deflate::Faster: 311,229 ops/s (+30% / 1.3x faster)
Roundtrip:
Gzip::Faster: 16,286 ops/s
Deflate::Faster (lvl 6): 52,813 ops/s (+224% / 3.2x faster)
Payload: Large text (100 KB, alternating 8 diverse payloads)
Compression:
Gzip::Faster: 1,203 ops/s
Deflate::Faster (lvl 6): 1,575 ops/s (+31% / 1.3x faster)
Deflate::Faster (lvl 1): 4,931 ops/s (+310% / 4.1x faster)
Decompression:
Gzip::Faster: 6,998 ops/s
Deflate::Faster: 23,530 ops/s (+236% / 3.4x faster)
Roundtrip:
Gzip::Faster: 1,022 ops/s
Deflate::Faster (lvl 6): 1,500 ops/s (+47% / 1.5x faster)
Payload: Huge text (1 MB, alternating 8 diverse payloads)
Compression:
Gzip::Faster: 117 ops/s
Deflate::Faster (lvl 6): 160 ops/s (+37% / 1.4x faster)
Deflate::Faster (lvl 1): 507 ops/s (+335% / 4.4x faster)
Decompression:
Gzip::Faster: 774 ops/s
Deflate::Faster: 2,595 ops/s (+235% / 3.4x faster)
Roundtrip:
Gzip::Faster: 101 ops/s
Deflate::Faster (lvl 6): 150 ops/s (+49% / 1.5x faster)
To avoid synthetic microbenchmark pitfalls (such as CPU L1 cache pinning and branch predictor over-training from looping over the exact same static buffer), the benchmarks cycle across eight diverse, realistic payloads per size tier (JSON API responses, HTML DOM trees, C/XS source code, HTTP access logs, English prose, SQL database transactions, cluster configuration, and CSV records).
Deflate::Faster demonstrates substantial compression throughput gains across all payload sizes (up to 7.2x faster at level 1 and up to 5.8x faster at level 6). Decompression is 1.3x to 3.4x faster on medium, large, and huge payloads, with roundtrip throughput up to 5.6x faster.
Comparison with Gzip::Libdeflate
Both Deflate::Faster and Gzip::Libdeflate are Perl wrappers around libdeflate. However, their design goals and feature sets differ:
Drop-in compatibility:
Deflate::Fasterprovides familiar procedural and OO interfaces matching Gzip::Faster. Gzip::Libdeflate has no procedural exports and uses an incompatible OO-only API.Thread-local Engine Caching: Thanks to thread-local compressor and decompressor caching with POSIX thread destructors,
Deflate::Faster's proceduralgzip/gunzipavoid object creation and method dispatch while remaining leak-free across thread lifecycles. On small payloads, procedural calls are up to 9x faster than per-callGzip::Libdeflate->new(...)object creation.Dynamic buffer sizing for all formats:
Deflate::Fasterdynamically unpacks gzip, zlib, and raw DEFLATE streams without requiring the caller to know the uncompressed size. Gzip::Libdeflate requires the caller to specify the exact uncompressedsizein advance when decompressing zlib or raw DEFLATE data.Perl UTF-8 and metadata support:
Deflate::Fastersupports UTF-8 flag preservation, safety limits (max_sizeto guard against decompression bombs), and header metadata (file_name,mod_time).
Thread safety
Deflate::Faster caches compressor and decompressor contexts in thread-local storage (__thread / _Thread_local) paired with POSIX thread key destructors, ensuring that per-thread engine contexts are cleanly released upon thread termination without leaking memory.
Deflate::Faster implements CLONE_SKIP, ensuring that objects existing in a parent thread are safely isolated and not cloned into child threads upon thread creation.
Exports
By default, exports gzip, gunzip, gzip_file, gunzip_file, and gzip_to_file.
Exportable on demand: deflate, inflate, deflate_raw, inflate_raw, gunzip_to_file.
Export tag :all exports everything.
See also
Author
vividsnow
License
This software is copyright (c) 2026 by vividsnow.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.