Drupal website speed and performance tuning

Summary: A look at Drupal speed, performance, and scalability improvements recently made to the devdaily.com website.

I’ve read before that the secret to great Drupal performance is Cache, cache, cache,” and while I always knew that to be true, I didn’t know how true it was. After several recent tweaks to the devdaily.com website, I can say that is very true. (I documented this in detail in my Drupal Boost module performance article.)

Here’s a quick look at Drupal performance improvements almost anyone can make to get your Drupal website serving nearly 2,000 page-views per second.

Option 1: “I like slow Drupal performance” (Do nothing)

Starting with the slowest possible way to run Drupal, just install Drupal, add in a bunch of modules, blog to your heart’s content, and live with the slow performance and extremely limited scalability.

Option 2: Enable the built-in Drupal caching

To make your website a little faster, enable the built-in Drupal cache. Go to the admin/settings/performance URI, set Caching Mode to Normal, enable the Block Cache, and Optimize your CSS and JavaScript files.

Even with these settings enabled, it took my Drupal 6 installation 14.8 seconds to serve 1,000 page requests, using the Apache ab benchmarking/performance tool, hitting the website with five simultaneous threads.

(All the Drupal performance numbers I state in this article are on a dual-processor Intel Pentium 4 3.00GHz server, with 2GB RAM, running CentOS Linux.)

Option 3: Install the PHP APC Opcode Cache

One problem with PHP performance in general is that your PHP scripts are never compiled. Every time someone requests a Drupal/PHP page, the server reads the PHP source code from the filesystem, compiles the script into binary code, then runs that resulting code.

The APC Opcode Cache is a free tool that essentially compiles your PHP scripts into a binary format, so that entire step is skipped. By installing the APC Opcode Cache on this website, I was able to reduce the time to serve 1,000 page views from 14.8 seconds to just 4.2 seconds — a very healthy improvement.

Option 4: Install a page cache

If you really want to see your website fly, install a tool that will cache your Drupal website pages so they won't need to hit PHP or the database. As one possible example, I just installed the Drupal Boost module, and reduced the time to serve 1,000 page views down to an incredibly low 0.53 seconds.

While it's named the Drupal Boost module, this module works both inside Drupal and outside of Drupal. Inside Drupal, it turns your Drupal content into static files. Outside of Drupal, you tweak your Apache configuration files slightly so Apache will serve these static files to anonymous users, so it never needs to fire up Drupal, PHP, or MySQL.

By serving static files like this, my Drupal installation was able to improve from handling a lowly 67 requests per second to handling a whopping 1,875 requests per second(!).

If you can completely control your own Drupal installation, you can install other extremely powerful caching systems like Varnish, but if you're using any sort of shared web hosting service, using the Drupal Boost module can give you terrific performance improvements, and the only thing you need to be able to modify outside of Drupal is your Apache configuration file (typically a .htaccess file).

“Treat every moment as your last.
It is not preparation for something else.”
 
~ Shunryu Suzuki

Option 5: More caching - Don’t serve the files

An even better way to cache files is never to serve them at all. Okay, what I mean by this is that you never serve them to a visitor after they see the first web page from your website.

Using the Apache "Expires" setting (and possibly other settings), you can tell your website visitor's browser to cache CSS, JavaScript, and image files, so when they go to a second page on your website they won't have to reload those static "resource" files.

This is something I'm going to work on next on my website, and I'll try to remember to update this article after I've done that. You need the Apache mod_expires module to make this work, and I didn't compile that into Apache when I built it last.

Option 6: Use a Content Delivery Network (CDN)

In recent years Content Delivery Networks (CDN) have become another affordable resource for making your website load even faster. I recently started using the Amazon CloudFront CDN, which can deliver static files much faster to website visitors than my server can.

In short, you upload your content to CloudFront, change your web page source code to get the images, CSS, and JavaScript files from your CloudFront server, and instantly your website will be faster.

CloudFront works by caching your files on servers in different countries around the world, so when a user in Asia hits my website they'll get the file from fast servers close to them, and when someone in Europe hits the website they'll get the files from servers in Europe, and so on.

So far I've just moved my Drupal image files over to CloudFront. If and when I can figure out how to move my Drupal CSS and JavaScript files to CloudFront I'll do that as well. (I also have many pages on this website that are served outside of Drupal, and I serve them from CloudFront, but I'm trying to keep most of this discussion to Drupal performance.)

Option 7: Other Drupal performance tweaks

If you've seen this website before, and you're looking at this website in late June, 2011, you may have noticed that the images that link to social websites like Twitter, Reddit, StumbleUpon, and Facebook aren't showing at the moment. You may have also noticed that the Twitter block I usually show with my latest tweets is also not currently showing.

The reason for both of these current changes is that I'm trying to optimize their performance, and they aren't behaving well. In the case of the social links, they are served up by the Drupal Service Links module, and it's not made to serve images from remote websites, so I need to hack it a little. These are just CSS changes I need to make that I haven't gotten around to yet.

In the case of the Twitter block, I was trying to get away with using the Twitter Widget HTML and JavaScript code in a Drupal block, but that has let me down. I really like Twitter, but they have been notorious for website downtime, and I don't want my web pages hanging while your browser tries to retrieve content from Twitter.com. I believe there is a Drupal Twitter module, and I'll try setting that up next weekend. As I recall, it caches my tweets locally, which I prefer.

“Treat every moment as your last.
It is not preparation for something else.”
 
~ Shunryu Suzuki

Drupal website performance and scalability - Summary

I hope you can see the general pattern here: Cache, cache, and more cache. Going from slowest to fastest, we have:

  • Do nothing.
  • Use Drupal caching.
  • Use the PHP APC Opcode Cache to improve PHP performance.
  • Use Drupal Boost so you rarely even hit PHP or MySQL (by caching content to files on disk).
  • Tell user's browsers to cache your static content so they won't ask for it on subsequent page requests.
  • Move your static content to a CDN so your server never has to serve the files at all.

As you can see, this process moves from a) serve everything dynamically on every page request to b) serve as few files as you possibly can to fulfill a request.