Apache’s mod_deflate module provides the DEFLATE output filter that allows output from your server to be compressed before being sent to the client over the network.
There are two ways of enabling gzip compression:
- Using Apache’s mod_deflate
- Using output buffering
Encoding the output and setting the appropriate headers manually makes the code more portable. Keep in mind that there are hundreds of Linux distributions, each slightly different to significantly different. To allow portability the application should not make assumptions about the OS or config involved.
Using Apache
1. Enable mod_deflate
Debian/Ubuntu:
$ a2enmod deflate $ /etc/init.d/apache2 force-reload
2. Configure mode_deflate
$ nano /etc/apache2/mods-enabled/deflate.conf # # mod_deflate configuration # <IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/x-javascript DeflateCompressionLevel 9 BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html DeflateFilterNote Input instream DeflateFilterNote Output outstream DeflateFilterNote Ratio ratio </IfModule>
Using output buffering
Create a gzip compressed string in your bootstrap file:
try { $frontController = Zend_Controller_Front::getInstance(); if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) { ob_start(); $frontController->dispatch(); $output = gzencode(ob_get_contents(), 9); ob_end_clean(); header('Content-Encoding: gzip'); echo $output; } else { $frontController->dispatch(); } } catch (Exeption $e) { if (Zend_Registry::isRegistered('Zend_Log')) { Zend_Registry::get('Zend_Log')->err($e->getMessage()); } $message = $e->getMessage() . "\n\n" . $e->getTraceAsString(); /* trigger event */ }
Do you have information about the performance impact of using the 1-9 scale for the DeflateCompressionLevel setting?
optimal gzip compression level for html – 3
@Gerard No, sorry.
@AmdY Where did you get this info from?
Doesn’t the mod_deflate output filter automatically set the Content-Encoding header for matching MIME types? So in that case is it necessary to set the same header in PHP?
Yes, but if you are building portable applications, then you have to set the header in the application.
Maybe I’m missing something? To check my memory I tried a plain HTML file on a server with mod_deflate enabled. Response headers:
Date: Tue, 07 Jul 2009 02:09:45 GMT
Server: Apache/2.0.52 (Red Hat)
Last-Modified: Tue, 07 Jul 2009 02:09:03 GMT
Etag: “c68003-163-1b48cdc0”
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 259
Content-Type: text/html
200 OK
Firstly, Ubuntu (9.04) is already configured to use mod_deflate and php output is gziped automatically.
Secondly, mod_deflate is output filter thus for no Ubuntu system is enough to do:
AddOutputFilterByType DEFLATE text/html
(or AddOutputFilterByType DEFLATE application/x-httpd-php with FAST CGI)
and turn on mod_defalte (or follow the step 2)
You don’t have to encode output as you described in the step 3 but you only have to set proper Content-type header (text/html) to get gzip worked.
@Gerard:
There is only increased memory consumption and little bit (between 1-9) of CPU time:
Compression: 400k + ( 8 x block size )
Block size is 900k for 9 and 100k for 1. Compression ratio is growing up with block size. As was mentioned 3 or 4 is a good start but I recommend to use 9 always.
I your server serve 1k request *simultaneously* you need at least (400k + (8 * 900k)) * 1k ~ 8GB ram…
@Ondrej
I’m using Fedora 8 and Ubuntu 8.04. I didn’t know 9.04 enabled the module by default (it makes sense), thanks for the tip. However, I do recommend having some guidelines for increasing portability during each of the key activities of development and maintenance, such as setting headers and compressing output.
It’s not special to Ubuntu 9.04. I would rather expect it to be related to Apache version – I’ve set up mod_deflate for an Apache 2, Debian 4 install, gzip compression was handled automatically with no php intervention.
@Federico
I forgot emphasize main idea that you don’t have to do anything which is mentioned in the step 3 when you set the correct Content-type header (and you have proper setup).
@Ondrej Are you saying that if you enable and configure the deflate module in Apache the output is automatically encoded and the headers automatically added regardless of the web server and operating system you are using?
@Federico
As Fake51 mentioned Apache 2.0 (and higher) should this do automatically when you turn on mod_deflate and the output from the php script has correct Content-type header.
As usual I forgot something:
Content negotiation (step 3 in your sample) is provided by mod_negotiation which is compiled by default in to Apache 2.0 or higher.
This has been my experience as well. Including:
AddOutputFilterByType DEFLATE text/html
in the vhost is enough to compress any text/html content (including PHP output), and set all the appropriate headers.
I’ve been using it for a while on both Ubuntu and CentOS servers and have never done anything like you have in step 3.
Yes, you are right. I’m going to edit the post and some of my comments.
So basically there are 2 methods for compressing the content:
1. Using Apache: Enable and configure mod_deflate and the server will automatically encoded the content and set the appropriate headers.
2. Using PHP: Encode the content and manually set the headers in the application.
Barry, Ondrej, Fake51 and Tim: Thanks for the corrections and extra info!
The post has now been updated.