rfc:modern_compression

PHP RFC: Modern Compression

Introduction

Integrating zstd (Zstandard) and 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 Composer and Symfony AssetMapper that cannot reasonably require PECL extensions or external commands to leverage these formats.

Proposal

We propose including the zstd and 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 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 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 is not currently supported by Safari and - at the highest compression level - Brotli 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

  1. the version(s) it was merged into
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature
  4. a link to the language specification section (if any)

References

zstd/brotli extension maintainer approval https://github.com/kjdev/php-ext-zstd/issues/72

rfc/modern_compression.txt · Last modified: 2025/02/18 10:08 by dunglas