Adventures in Drupal performance tuning: Minimizing bandwidth usage

Drupal and Apache configuration tips to give your site a slimmer figure

Now that we’ve successfully learned how to speed up our site on the sever end with cache the next step, in my mind, is to learn about different ways we can increase the speed in which a client downloads your site.  We can do this by reducing the quantity and size of the files that are downloaded.

Yahoo and Google have both spearheaded a push in this direction with the firefox addons they’ve released to help test against certain criteria. Page Speed and YSlow both give your site a rating of how optimized it is. What we will do now is attempt to setup our server to accomplish some of these recommendations.

Let’s set some intelligent Drupal settings

Before we start messing around with backend server settings there are some simple drupal specific configuration options you can set to significantly reduce the amount of overheard your site produces. In your drupal administrative area, head on over to /admin/settings/performance and make sure the following settings are configured:

Compressing content with mod_deflate

If your web server doesn’t have a cap on the monthly bandwidth you can use then your ISP is probably charging you per GB. Since bandwidth is such a finite resource, why not do what you can to minimize the usage of it?

This is where mod_deflate comes in. When you have the module configured and enabled, it intercepts all content that apache will distribute and does a very important thing to it. It compresses it! It uses a standard compression mechanism, not to dissimilar to that used in zip files, to shrink the size of whatever files you tell it should shrink . This compression, when used on text files, produces dramatic results. Take the homepage HTML of this site. The raw html is 28.1 KB. When it is sent out using mod_deflate, it’s only 7.3 KB. That’s almost a 75% reduction in size! Bazinga!

Before we enable the module, let’s make sure it’s configured properly. On an ubuntu or debian based server enter nano /etc/apache2/mod-available/deflate.conf to open up the mod_deflate configuration file. If your starting from scratch here is a good place to start:

<IfModule mod_deflate.c>
        DeflateCompressionLevel 9
        SetOutputFilter DEFLATE
        SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|exe|t?gz|zip|bz2|sit|rar|pdf)$ no-gzip dont-vary

   # Netscape 4.X has some problems
        BrowserMatch ^Mozilla/4 gzip-only-text/html

   # Netscape 4.06-4.08 have some more problems
        BrowserMatch ^Mozilla/4\.0[678] no-gzip

   # MSIE masquerades as Netscape, but it is fine
        BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

   # Setup custom deflate log
   #        DeflateFilterNote Input instream
   #        DeflateFilterNote Output outstream
   #        DeflateFilterNote Ratio ratio
   #        LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate

   # Example of log file (add to vhosts)
   #        CustomLog logs/deflate_log DEFLATE

As you look through whats there, you will hopefully notice a couple things:

Now that our configuration is set, it’s time to enable the module: a2enmod deflate. You can restart apache now if you want or wait until were done. It’s up to you. 

For more information check out the mod_deflate documentation.

Encourage browsers to use cached files with mod_expires

Now that a browser has downloaded our slender & compressed files, how do we encourage it to not re-download them when it’s not necessary? We do this by using another apache module called mod_expires. What mod_expires does is it adds additional information in the HTTP header that tells the browser “Do not check for newer versions of this fill until X date.” Browsers typically do a lot of caching on their own, mod_expires simply encourages the behavior by being much more explicit. It’s kind of like your mother with a stern look and her hands on her hips. 

To get things going, open up the mod_expires configuration file: nano /etc/apache2/mod-available/expires.conf and add the following:

<IfModule mod_expires.c>
    ExpiresActive onExpiresDefault "access plus 6 months"

    ExpiresByType image/x-icon "modification plus 5 years" 
    ExpiresByType image/png "modification plus 5 years" 
    ExpiresByType image/jpg "modification plus 5 years" 
    ExpiresByType image/gif "modification plus 5 years"
    ExpiresByType image/jpeg "modification plus 5 years"
    ExpiresByType application/pdf "modification plus 5 years"

    ExpiresByType text/css "modification plus 5 years"
    ExpiresByType text/javascript "modification plus 5 years"

What we’ve got here is a list of files that typically do not change after they have been uploaded to the server. I’ve also added CSS and Javascript files here. Since we enabled CSS and JS file optimization in the drupal settings the resulting combined filenames will be a random sequence of letters and numbers, such as css_1d8f38282c64a582f9c0848efeaad140.css. If you need to make a change to your sites css sheet, you will also need to refresh your cache. This will create a completely new combined css file so there is no need to worry about users not receiving css and js updates. 

Once your done with adding the configuration options, make sure to enable the modulea2enmod expires then to restart apache /etc/init.d/apache2 restart

The fruits of our labor

To test, I simply used firebug to look at file sizes and counts. You could get a lot more specific, like enabling mod_deflate logging, but firebug was enough for me. I must admit that I’m blown away by the drastic change in the number of files as well as the total size of my site after making these changes. If I take just the html, css and javascript files (so not including the images) the results are as follows:

Number of files18666% reduction!
Total Size131.5 KB43.8 KB77% reduction!

Can you believe it? What were your improvements?

Some other considerations

There are many ways you can build your site to save on bandwidth. Here are a couple more things you can look into:

Recent posts