A little-used or discussed feature of PHP is the ability to compress output from the scripts using GZIP for more efficient transfer to requesting clients. By automatically detecting the ability of the requesting clients to accept and interpret GZIP encoded HTML, PHP4 can decrease the size of files transferred to the client by 60% to 80%.
The information given here is known to work on systems running Red Hat 8.0, Apache/1.3.27, Apache/2.0.44 and PHP/4.3.1.
[Note: Although not re-tested since this article was originally written, compression is still present in the PHP 5.x releases and can be used to effectively compress content on shared or hosted servers where compression is not enabled within the Web server.]
Configuring PHP
The configuration needed to make this work is simple. Check your installed Red Hat RPMS for the following two packages:
- zlib
- zlib-devel
For those not familiar with zlib, it is a highly efficient, open-source compression library. This library is used by PHP uses to compress the output sent to the client.
Compile PHP4 with your favourite ./configure statement. I use the following:
Apache/1.3.27
./configure –without-mysql –with-apxs=/usr/local/apache/bin/apxs –with-zlib
Apache/2.0.44
./configure –without-mysql –with-apxs2=/usr/local/apache2/bin/apxs –with-zlib
After doing make && make install, PHP4 should be ready to go as a dynamic Apache module. Now, you have to make some modifications to the php.ini file. This is usually found in /usr/local/lib, but if it’s not there, don’t panic; you will find some php.ini* files in the directory where you unpacked PHP4. Simply copy one of those to /usr/local/lib and rename it php.ini.
Within php.ini, some modifications need to be made to switch on the GZIP compression detection and encoding. There are two methods to do this.
Method 1:
output_buffering = On
output_handler = ob_gzhandler
zlib.output_compression = Off
Method 2:
output_buffering = Off
output_handler =
zlib.output_compression = On
Once this is done, PHP4 will automatically detect if the requesting client accepts GZIP encoding, and will then buffer the output through the gzhandler function to dynamically compress the data sent to the client.
The ob_gzhandler
The most important component of this entire process is placing the ob_gzhandler PHP command on the page itself. It needs to be placed in the code at the top of the page, above the HTML tag in order to work. It takes the addition of the following line to complete the process:
<?php ob_start("ob_gzhandler"); ?>
In WordPress installs, this becomes the first line in the HEADER.PHP file. But be careful to check that it’s working properly. If the Web application has the compression function built into it, and you add the ob_gzhandler function, a funky error message will appear at the top of the page telling you that your can’t invoke compression twice.
Web servers with native compression are smarter than that – they realize that the file is already compressed and don’t run it through the compression algorithm again.
Once this is in place, you will be able to verify the decrease in size using any HTTP browser capture tool (Firebug, Safari Web Inspector, Fiddler2, etc.)
So?
The winning situation here is that for an expenditure of $0 (except your time) and a tiny bit more server overhead (you’re probably still using fewer resources than if you were running ASP on IIS!), you will now be sending much smaller, dynamically generated html documents to your clients, reducing your bandwidth usage and the amount of time it takes to download the files.
How much of a size reduction is achieved? Well, I ran a test on my Web server, using WGET to retrieve the file. The configuration and results of the test are listed below.
Method 0: No Compression wget www.pierzchala.com/resume.php | File Size: 9415 bytes |
Method 1: ob_gzhandler wget –header=”Accept-Encoding: gzip,*” www.pierzchala.com/resume.php | File Size: 3529 bytes |
Method 2: zlib.output_compression wget –header=”Accept-Encoding: gzip,*” www.pierzchala.com/resume.php | File Size: 3584 bytes |
You will have to experiment with the method that give the most efficient balance between file size and overhead and processing time on your server.
A 62% reduction in transferred file size without affecting the quality of the data sent to the client is a pretty good return for 10 minutes of work. I recommend including this procedure in all of your future PHP4 builds.
2009-02-12 — 09:21
Can you please let me know how much overhead it would be on my server. I've VPS plan with about 50 sites hosted.- Shobhithttp://shobhit.net/
2009-02-16 — 13:05
It shouldn't affect you performance to any great degree as it is used in many production environments currently.However, if you do have the ability to do compression inside of the Web server itself (Apache, IIS, etc.), I would recommend that over adding compression at the application layer.smp
2009-02-16 — 20:05
It shouldn't affect you performance to any great degree as it is used in many production environments currently.However, if you do have the ability to do compression inside of the Web server itself (Apache, IIS, etc.), I would recommend that over adding compression at the application layer.smp
2012-01-09 — 17:30
Steph,
Thanks for the post.
Using zlib, I want to have content flushed at 3072 and compressed at level 4.
For
zlib.output_handler = On
and
implicit_flush = Off
is this OK ?
Many thanks, and good luck with consultancy business.
radu
output_buffering = Off
output_handler =
zlib.output_compression = 3072
zlib.output_compression_level = 4
zlib.output_handler = On
implicit_flush = Off