====== PHP RFC: Modern Compression ======
* Version: 1.0
* Date: 2025-02-18
* Author: Jordi Boggiano (j.boggiano@seld.be), Kévin Dunglas (kevin@dunglas.fr)
* Status: Under Discussion
* First Published at: http://wiki.php.net/rfc/modern_compression
===== Introduction =====
Integrating [[https://datatracker.ietf.org/doc/html/rfc8878|zstd]] (Zstandard) and [[https://datatracker.ietf.org/doc/html/rfc7932|brotli]] compression formats into PHP's core would significantly enhance the language's data compression capabilities.
These modern algorithms offer superior compression ratios and speeds compared to gzip. By embedding them directly into PHP, developers would have access to efficient, web-native compression methods without relying on external extensions. Integrating these would also pave the way for tools like [[https://getcomposer.org|Composer]] and [[https://symfony.com/doc/current/frontend/asset_mapper.html|Symfony AssetMapper]] that cannot reasonably require PECL extensions or external commands to leverage these formats.
===== Proposal =====
We propose including the [[https://github.com/kjdev/php-ext-zstd|zstd]] and [[https://github.com/kjdev/php-ext-brotli|brotli]] extensions. The implementation involves incorporating the stable, mature C libraries of zstd and brotli, and exposing their functionalities through new PHP functions. Since these libraries are well-established and their APIs are stable, the maintenance overhead would be minimal.
Benefits:
* Enhanced Performance: Both Zstandard and Brotli offer higher compression ratios and faster decompression times compared to legacy algorithms, leading to reduced storage requirements and faster data transmission.
* Web-Native Formats: As these formats are supported by modern web browsers and servers, their inclusion aligns PHP with current web standards and practices.
* Minimal Maintenance: The libraries are stable, and the PHP extensions are straightforward wrappers around the C APIs, ensuring low maintenance demands.
* Composer Integration: Native support would allow Composer to utilize these algorithms for package compression, resulting in smaller package sizes and quicker installations.
* Assets pre-compression: Modern web servers such as [[https://caddyserver.com/docs/caddyfile/directives/file_server#precompressed|Caddy/FrankenPHP]] and NGINX (with modules) support serving pre-compressed static files instead of compressing them on the fly, saving CPU-time and decreasing latency. Tools such as Symfony AssetMapper [[https://symfony.com/doc/7.3/frontend/asset_mapper.html#pre-compressing-assets|are adding support for assets pre-compression]] and would benefit from not requiring external PECL extensions or system commands.
Although Zstandard is in most cases more efficient than Brotli, Zstandard [[https://caniuse.com/?search=zstandard|is not currently supported by Safari]] and - at the highest compression level - Brotli [[https://paulcalvano.com/2024-03-19-choosing-between-gzip-brotli-and-zstandard-compression/|produces smaller files]] than Zstandard. As browsers negotiate which format to use according to their capabilities, we propose adding support for both formats to PHP.
==== Zstandard ====
The zstd implementation includes a few global functions as well as namespaced ones
zstd_compress — Zstandard compression
zstd_uncompress — Zstandard decompression
zstd_compress_dict — Zstandard compression using a digested dictionary
zstd_uncompress_dict — Zstandard decompression using a digested dictionary
namespace Zstd;
function compress( $data [, $level = \ZSTD_COMPRESS_LEVEL_DEFAULT ] )
function uncompress( $data )
function compress_dict ( $data, $dict )
function uncompress_dict ( $data, $dict )
There is also support for output compression and a stream wrapper (''compress.zstd'' scheme).
==== Brotli ====
The brotli implementation includes a few global functions as well as namespaced ones
brotli_compress — Compress a string
brotli_uncompress — Uncompress a compressed string
brotli_compress_init — Initialize an incremental compress context
brotli_compress_add — Incrementally compress data
brotli_uncompress_init — Initialize an incremental uncompress context
brotli_uncompress_add — Incrementally uncompress data
namespace Brotli;
function compress( $data [, $quality = \BROTLI_COMPRESS_LEVEL_DEFAULT, $mode = \BROTLI_GENERIC ] )
function uncompress( $data [, $length = 0 ] )
function compress_init( [ $quality = \BROTLI_COMPRESS_LEVEL_DEFAULT, $mode = \BROTLI_GENERIC ] )
function compress_add( resource $context, string $data [, $mode = \BROTLI_FLUSH] )
function uncompress_init()
function uncompress_add( resource $context, string $data [, $mode = \BROTLI_FLUSH] )
There is also support for output compression and a stream wrapper (''compress.brotli'' scheme).
===== Backward Incompatible Changes =====
None beyond new global function names being taken.
===== Proposed PHP Version(s) =====
Next PHP minor release (8.5)
===== RFC Impact =====
==== To SAPIs ====
None.
==== To Existing Extensions ====
None.
==== To Opcache ====
None.
==== New Constants ====
^ Constant ^ Description ^
| ZSTD_COMPRESS_LEVEL_MIN | Minimal compress level value |
| ZSTD_COMPRESS_LEVEL_MAX | Maximal compress level value |
| ZSTD_COMPRESS_LEVEL_DEFAULT | Default compress level value |
| LIBZSTD_VERSION_NUMBER | libzstd version number |
| LIBZSTD_VERSION_STRING | libzstd version string |
| | |
| BROTLI_COMPRESS_LEVEL_MIN | Minimal compress level value |
| BROTLI_COMPRESS_LEVEL_MAX | Maximal compress level value |
| BROTLI_COMPRESS_LEVEL_DEFAULT | Default compress level value |
| BROTLI_GENERIC | Default compression mode |
| BROTLI_TEXT | UTF-8 format text input compression mode |
| BROTLI_FONT | WOFF 2.0 font compression mode |
| BROTLI_FLUSH | For incremental compression, produce output for all processed input |
| BROTLI_PROCESS | For incremental compression, process input, encoder may postpone producing output, until it has processed enough input |
| BROTLI_FINISH | For incremental compression, finalize the stream |
==== php.ini Defaults ====
Both extensions provide basic ini settings for output compression that are disabled by default.
zstd.output_compression default 0
zstd.output_compression_level default -1
zstd.output_compression_dict default ""
brotli.output_compression default 0
brotli.output_compression_level default -1
===== Open Issues =====
None.
===== Unaffected PHP Functionality =====
No existing functionality should be affected.
===== Future Scope =====
None.
===== Proposed Voting Choices =====
Yes or no vote. 2/3 required to pass.
===== Patches and Tests =====
Inclusion in core will be done by Kévin Dunglas (unless someone else volunteers) once the RFC approved.
===== Implementation =====
After the project is implemented, this section should contain
- the version(s) it was merged into
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
- a link to the language specification section (if any)
===== References =====
zstd/brotli extension maintainer approval https://github.com/kjdev/php-ext-zstd/issues/72