Increase speed and reduce bandwidth usage with ZF and Apache
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 PHP’s built-in functions
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 PHP
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?
Gerard Klomp
July 6, 2009 at 12:49 pm
optimal gzip compression level for html – 3
AmdY
July 6, 2009 at 12:50 pm
@Gerard No, sorry.
@AmdY Where did you get this info from?
Federico
July 6, 2009 at 3:26 pm
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
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
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
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
@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
@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
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
@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
@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
@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
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
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
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
The post has now been updated.
Federico
July 8, 2009 at 9:52 am
[...] original article was written by Federico Cargnelutti and I consider it very good and blog [...]
Cristian Neagu
July 9, 2009 at 8:32 am