Federico Cargnelutti

Simple is better than complex. Complex is better than complicated. | @fedecarg

Increase speed and reduce bandwidth usage

with 18 comments

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:

  1. Using Apache’s mod_deflate
  2. 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 */
}

Reference

Use mod_deflate to compress Web content delivered by Apache


Written by Federico

July 6, 2009 at 11:09 am

18 Responses

Subscribe to comments with RSS.

  1. Do you have information about the performance impact of using the 1-9 scale for the DeflateCompressionLevel setting?

    Gerard Klomp

    July 6, 2009 at 12:49 pm

  2. optimal gzip compression level for html – 3

    AmdY

    July 6, 2009 at 12:50 pm

  3. @Gerard No, sorry.

    @AmdY Where did you get this info from?

    Federico

    July 6, 2009 at 3:26 pm

  4. 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?

    Barry Austin

    July 6, 2009 at 5:50 pm

  5. Yes, but if you are building portable applications, then you have to set the header in the application.

    Federico

    July 6, 2009 at 10:07 pm

  6. 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

    Barry Austin

    July 7, 2009 at 2:37 am

  7. 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.

    Ondrej Ivanic

    July 7, 2009 at 5:33 am

  8. @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 Ivanic

    July 7, 2009 at 8:09 am

  9. @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.

    Federico

    July 7, 2009 at 8:25 am

  10. 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.

    Fake51

    July 7, 2009 at 11:10 am

  11. @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

    July 7, 2009 at 2:38 pm

  12. @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

    July 7, 2009 at 6:15 pm

  13. @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.

    Ondrej Ivanic

    July 8, 2009 at 5:37 am

  14. 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.

    Ondrej Ivanic

    July 8, 2009 at 5:41 am

  15. 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.

    Tim Fountain

    July 8, 2009 at 9:00 am

  16. 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!

    Federico

    July 8, 2009 at 9:34 am

  17. The post has now been updated.

    Federico

    July 8, 2009 at 9:52 am

  18. [...] original article was written by Federico Cargnelutti and I consider it very good and blog [...]

    Cristian Neagu

    July 9, 2009 at 8:32 am


Leave a Reply