$30 off During Our Annual Pro Sale. View Details »

HTTP compression in PHP and Symfony apps

HTTP compression in PHP and Symfony apps

Compressing HTTP responses can significantly improve the performance of your PHP and Symfony applications. But you must still navigate the jungle of standards and formats.

In this presentation, we'll discover how HTTP compression works, the different formats supported by modern web browsers (deflate, gzip, Brotli, and the brand-new Zstandard), and how to use them correctly.

We'll also look at which formats to compress, which not to, when to use dynamic compression, and when (and how) to pre-compress responses that can be compressed for even better performance.

Kévin Dunglas

December 05, 2024
Tweet

More Decks by Kévin Dunglas

Other Decks in Programming

Transcript

  1. Kévin Dunglas ➔ Co-founder of Les-Tilleuls.coop ➔ Symfony Core Team

    ➔ Creator of API Platform, FrankenPHP and Mercure ➔ Maintainer of Caddy @dunglas
  2. The process of encoding information using fewer bits than the

    original representation. WIKIPEDIA What is compression?
  3. Why is Compression Useful for Web Apps? ➔ Reduces the

    size of resources to be transmitted ➔ Can reduce the time needed to download (or upload) a resource through a network ➔ Saves bandwidth ➔ Key factor in website performance (HTTP responses can be compressed) Photo by Denny Müller
  4. Efficiency Depending on the file, the compression format and level,

    compression can reduce the size of a file from 2 to 3 times
  5. ➔ Space-time tradeoff: • compressing and decompressing takes computational resources

    (CPU, RAM) • and (some) time to execute the algorithm ➔ In the HTTP context, compression is useful if: • it decreases latency (the time required for encoding/decoding is less than the time required to download the deleted data) • additional computation costs do not exceed saved bandwidth costs Compression is a Tradeoff Photo by Mathew Schwartz
  6. Lossy or Lossless Lossless compression: ➔ no loss of information

    after decoding ➔ ZIP, gzip, Brotli, PNG, GIF… ➔ Best for HTML, JS, CSS, SVG ➔ Focus of this talk Lossy compression: ➔ Inexact approximation ➔ data (quality) loss ➔ JPEG, MPEG, MP3…
  7. Useful for most HTTP responses (but not all, wait for

    it!) Two popular techniques: ➔ Huffman coding assigns the shortest possible code to each transferred symbol, or group of symbols ➔ Static dictionaries share symbols between the client and the server Some formats support custom dictionaries, but it’s not supported by browsers yet They can be combined! Lossless Compression Photo by Niklas Ohlrogge
  8. ➔ Define how hard the compressor looks for matching strings

    (how many symbols to use in the Huffman tree) ➔ The higher the level: • the smaller the final size • the most time-consuming and CPU-intensive ➔ Remember: compression is a tradeoff Compression Levels Photo by Florian Hahn
  9. Words from Brotli's dictionary (13504 in all) time जानकारी the

    University of <!DOCTYPE html PUBLIC " (){\n text-decoration:under CIA World Factbook .JPG
  10. ➔ zstd (Zstandard), Facebook, 2016 ➔ br: (Brotli), Google, 2013

    ➔ gzip, GNU, 1996 ➔ deflate, GNU, 1996 ➔ compress, Lempel-Ziv-Welch, 1984 ➔ identity, no compression or modification Supported Formats in Accept-Encoding Photo by Maksym Kaharlytskyi
  11. Benchmarks Compressor name Ratio Compression Decompression zstd 1.5.6 -1 2.887

    510 MB/s 1580 MB/s zlib 1.2.11 -1 2.743 95 MB/s 400 MB/s brotli 1.0.9 -0 2.702 395 MB/s 430 MB/s Source: Facebook
  12. A surprising amount of sites are using low level gzip

    compression, and should consider increasing their compression levels. ➔ For dynamic content ◦ Brotli level 5 usually results in smaller payloads, at similar or slightly slower compression times. ◦ zStandard level 12 often produces similar payloads to Brotli level 5, with compression times faster than gzip and Brotli. ➔ For static content ◦ Brotli level 11 produces the smallest payloads ◦ zStandard is able to apply their highest compression levels much faster than Brotli, but the payloads are still smaller with Brotli. PAUL CAVANO - Choosing Between gzip, Brotli and zStandard Compression (19 Mar 2024) State of the art
  13. What to compress? ➔ Everything… ➔ …except formats already compressed

    • JPEG, PNG, GIF • WebP (sometimes) • WOFF/WOFF2 fonts • XLSX, DOCX, PPTX… • PDF (sometimes) • ZIP, gz, bz2, RAR… • binaries (sometimes) ➔ especially efficient with text files Photo by Glenn Carstens-Peters
  14. ➔ “on the fly” compression ➔ Compression can be done

    by: • PHP itself (not my recommendation) • The origin web server • The CDN ➔ Prefer Zstandard • Fallback on Brotli ◦ Fallback on gzip ➔ Use a fast compression level to not increase latency Dynamic Content (HTML, JSON…) Photo by Crystal Kwok
  15. FrankenPHP / Caddy (Dynamic Content) encode zstd br gzip #

    br is natively supported by FrankenPHP. # With Caddy, you need github.com/dunglas/caddy-cbrotli # (uses cgo)
  16. NGINX (gzip, Dynamic Content) gzip on; # http://blog.klauspost.com/gzip-performance-for-go-webservers/ gzip_comp_level 5;

    # text/html is always compressed gzip_types text/css text/javascript; # ... gzip_proxied no-cache no-store private expired auth; gzip_min_length 512; gzip_vary on;
  17. BREACH Attack (2012) ➔ Compression side-channel attack ➔ Data can

    leak, even if the content is encrypted with TLS ➔ To be affected, the page must: • Be compressed • Reflect user data (POST, query param…) • Contain a secret that doesn’t change at each request ➔ Symfony CSRF tokens are safe by default ➔ The new stateless CSRF feature introduced in Symfony 7.2 is perfect for this use case Photo by Chris Lynch
  18. Is your CDN modifying the response? (ex: CloudFlare proxy, WAF,

    optimizers…) ➔ yes • Don’t compress, or compress as a low (fast) level • Your CDN will decompress the response from the origin server, then re-compress it ➔ no • Compress as usual, the CDN will just proxy the response CDN and Dynamic Content Photo by Diana Polekhina
  19. ➔ Precompress! ➔ Use the most efficient (slowest) level •

    Compressed only one time ➔ Prefer Brotli • Fallback on Zopfli, a reimplementation of Gzip slower but more efficient Static files (JS, CSS, SVG, static HTML…) Photo by Nicolas Picard
  20. Usage bin/console asset-map:compile # All assets will be compressed in

    Brotli, Zstandard and Gzip # The extension is appended to the original file name: # foo.js foo.js.br foo.js.zst foo.js.gz bin/console asset:compress robots.txt # The file passed as argument is compressed # robots.txt robots.txt.br robots.txt.zst robots.txt.gz # A asset_mapper.compressor is also available (ex: file upload)
  21. ➔ Webpack: compression-webpack-plugin ➔ Rollup / Vite: rollup-plugin-gzip ➔ Both

    support Brotli, Zopfli and gzip, but not Zstandard JavaScript Tools
  22. NGINX (Static Content) gzip_static on; gzip_proxied expired no-cache no-store private

    auth; # Needs https://github.com/google/ngx_brotli brotli_static on # Needs https://github.com/tokers/zstd-nginx-module zstd_static on;
  23. Apache (Static Content) AddEncoding gzip .gz AddEncoding br .br #

    Zstandard is not supported RewriteCond %{HTTP:Accept-encoding} gzip RewriteCond %{REQUEST_FILENAME}\.gz -s RewriteRule ^(.*)\ $1\.gz [QSA] RewriteCond %{HTTP:Accept-encoding} br RewriteCond %{REQUEST_FILENAME}\.br -s RewriteRule ^(.*)\ $1\.br [QSA] # Serve correct content types, and prevent double compression. RewriteRule \.css\.gz$ - [T=text/css,E=no-brotli:1] RewriteRule \.js\.gz$ - [T=text/javascript,E=no-brotli:1] RewriteRule \.css\.br$ - [T=text/css,E=no-gzip:1] RewriteRule \.js\.br$ - [T=text/javascript,E=no-brotli:1] # ...
  24. ➔ Compression is one of the easiest and most efficient

    ways to improve webperf, use it! ➔ Compress dynamic content using Zstandard ➔ Pre-compress static content with Brotli at the highest level (Use the new Symfony AssetMapper pre-compression feature) ➔ Using FrankenPHP and Caddy is the easiest way to serve compressed responses with modern efficient formats! Take Away
  25. Web and Cloud Experts ➔ Dev: PHP, JS, Go, Rust...

    ➔ DevOps and SRE ➔ Consultancy and maintenance ➔ Agile management, UX and UI design… ➔ [email protected] 💌
  26. Thank you! ➔ Come at our booth for swag, questions

    and discussions! les-tilleuls.coop [email protected] @coopTilleuls