FU::Util: Add gzip_compress() wrapper for libdeflate/zlib-ng/zlib

And use it for automatic output compression in FU, as (potentially)
faster alternative to Compress::Raw::Zlib.

Was also planning to maybe add support for Zstd or Brotli, but given the
performance of libdeflate, I'm not sure that's really necessary. Brotli
does tend to do a better job at compressing HTML, though.
This commit is contained in:
Yorhel 2025-03-18 16:58:31 +01:00
parent c2e0f158ac
commit bc33fe53f0
5 changed files with 237 additions and 10 deletions

View file

@ -13,6 +13,7 @@ our @EXPORT_OK = qw/
utf8_decode uri_escape uri_unescape
query_decode query_encode
httpdate_format httpdate_parse
gzip_lib gzip_compress
fdpass_send fdpass_recv
/;
@ -367,6 +368,48 @@ This will not happen if your local timezone is UTC.
=back
=head2 Gzip Compression
Gzip compression can be done with a few different libraries. The canonical one
is I<zlib>, which is old and not well optimized for modern systems. There's
also I<zlib-ng>, a (much) more performant reimplementation that remains
API-compatible with I<zlib>. And there's I<libdeflate>, which offers a
different API that does not support streaming compression but is, in exchange,
even faster than I<zlib-ng>.
There are more implementations, of course, but this module only supports those
three and (attempts to) pick the best one that's available on your system.
=over
=item gzip_lib()
Returns an empty string if no supported gzip library was found on your system
(unlikely but possible), otherwise returns the selected implementation: either
C<"libdeflate">, C<"zlib-ng"> or C<"zlib">.
This function does not try very hard to differentiate between I<zlib> and
I<zlib-ng>, so it may report that I<zlib> is being used on systems where
C<libz.so> is, in fact, I<zlib-ng>.
=item gzip_compress($level, $data)
Returns a byte string with the gzip-compressed version of C<$data> at the given
gzip C<$level>, which is a number between 0 (no compression) and 12 (strongest
compression). Only I<libdeflate> supports levels higher than 9, for
I<zlib(-ng)> the level is capped at 9. 6 is typically used as a default.
Throws an error if no suitable library was found.
=back
This module does not currently implement decompression. If you need that, or
streaming, or other functionality not provided here, there's
L<Compress::Raw::Zlib> and L<Compress::Zlib> in the core Perl distribution and
L<Gzip::Deflate> on CPAN.
=head2 File Descriptor Passing
UNIX sockets (see L<IO::Socket::UNIX>) have the fancy property of letting you