Web Performance: A Guide to Building Fast Drupal Websites
What follows is part one in a series of posts on web performance that I've wanted to write for quite some time. In this series of posts I'll not only be talking about optimizing web performance generally, but also providing specific guidance for speeding up Drupal sites.
Although I'm not a web performance specialist or expert, I have taken a keen interest in the topic in my work as a frontend developer building responsive websites. I love building fast sites and have gained some experience over the years getting Drupal to shed some its inherent sluggishness.
As a way of systematically tackling what can be a complex subject, we'll use the results of a test from WebPageTest.org, a Google-sponsored tool that provides very in-depth information about the performance of a site in nice, easily digestible chunks.
How Fast Is Fast Enough?
Before we get into the details of web performance we should first stop to ask how fast a site should be in order to qualify as "fast". Here are some research results courtesy of Radware that might help bring things into focus:
- 64% of smartphone users expect pages to load in less than 4 seconds.
- The performance poverty line (i.e. the plateau at which your website’s load time ceases to matter because you’ve hit close to rock bottom in terms of business metrics) for most sites is around 8 seconds.
More guidance comes courtesy of Ilya Grigorek of Google. In his recent presentation at the Velocity conference, he cited research that indicates a target page render time should be 1000ms - or one second - to avoid "context switching" among users.
Basically, if it takes a page longer than one second to render, you risk losing the attention of the user. If it takes longer than eight seconds for a page to render, it's similar in terms of business metrics (conversions, sales, etc) as if it took 30 seconds or a minute.
If one second sounds impossibly ambitious, there is further research showing that a load time of three seconds or less is probably OK.
The bottom line: your pages should load in under three seconds on desktop, and under 4 seconds on a mobile.
Pretty harsh reality check, huh? Let's see what can be done to get our sites whipped into shape.
Test Results for this Analysis
In order for us to have a practical example for our discussion, I ran the Friendly Machine site through WebPageTest. Here are the results (click to enlarge image):
I recently completed a refresh of the design of this site with a lot of attention focused on keeping things fast. My target page load time was one second, so I was happy when the results consistently came in below that.
Let's start our analysis by looking at the first number in the above table - under the heading "Load Time". You'll see the value is 0.662 seconds. That's pretty darn good, but if you scan across the table you may see something on the far right that's a bit confusing - a Fully Loaded Time of 0.761 seconds.
So what's the difference between Load Time and Fully Loaded Time?
Load Time is calculated from the time when the user started navigating to the page until the Document Complete event is fired. The Document Complete event is fired by the browser once the page has completed loading.
The Fully Loaded time, on the other hand, also includes any metrics up until there is no network activity for two seconds. Most of the time this means watching for things being loaded by JavaScript in the background.
First Byte Time = Backend Performance
Whenever talk turns to web performance, it seems a lot of folks immediately start thinking of what's happening on the server. Although it's a very important piece of the puzzle, as we walk through this analysis, you'll see that most web performance issues actually reside on the frontend.
Before we get ahead of ourselves, though, let's return to the results from our test and look at the next metric in our table, First Byte Time (highlighted in blue below) which tells us about performance on the server.
This First Byte Time represents the time from when a user began navigating to the page until the first bit of the server response arrived at the browser. The target time for this on WebPageTest is a meager 87 ms!
This metric is also represented as the first in the series of letter grades you see at the top of the test results. You'll notice Friendly Machine got an "A" and I really wish I could take credit for it, but the truth is my host Pantheon - and the awesome backend performance they provide - are responsible for this metric scoring well.
Backend Drupal Performance
Let's pause here and talk specifically about backend Drupal performance. How would we address this metric if it hadn't scored well? This topic can get pretty deep, so we'll only review the most popular options, but they'll still be able to do wonders for improving this key metric if your site is not performing well.
Let's start by discussing server resources (with a brief, tangential mini-rant about shared hosting).
If you want a fast Drupal website, you really shouldn't be on a shared host, period. Although many of them will claim to be Drupal specialists, very few of them actually are. One giveaway is the number for PHP memory limit.
Although this number doesn't directly impact performance, it can break your site if it's too low and is also useful for smoking out hosts that don't know Drupal. You can find this number at admin/reports/status and it will look something like the image below.
You can see on my site this number is at 256 megabytes and this is most likely where you want it, although if you have a simple site without Views or Panels, then 128M might work. If it's set at 64M, then it's too low and this is often what you'll find with shared hosting arrangements.
Another issue with shared hosting - and one that does impact performance - is that your website is on a server with perhaps hundreds of other sites. If one of those sites gets hit with a large spike in traffic or some other issue, it can affect all the sites on that server as it gobbles up the available resources.
Perhaps the biggest issue with shared hosting, however, is that advanced caching using tools like Memcached and Varnish are rarely, if ever, available. And when it comes to Drupal backend performance, caching is critical. The best you'll probably be able to do with regard to caching on shared hosting is using the Boost module, which we'll talk about in the next section.
To ensure that server resources aren't an issue for your website, consider either a managed VPS or a Drupal host like Pantheon, both of which start at around $25 per month. Pantheon is what I recommend for small to medium sized sites because your site will scale better with them and they offer tremendous value, although they are a great fit for enterprise clients as well. If you have a bigger budget, Acquia or BlackMesh might fit the bill.
Sure, these options cost more than the $7 per month the cheap hosts offer, but they will provide a professional level of service that will more than pay for itself over time.
Caching for Drupal Websites
We said caching was critical, so here are five of the most important caching solutions for a Drupal website:
- Drupal's built-in caching
- Boost module
- Memcached
- Varnish
- Views caching
There are other options, of course, but these five cover most of the ground. Let's briefly go through them one at a time.
Drupal's Built-in Caching
Most of a Drupal site is stored in the database - nodes, information about blocks, etc. - and enabling the default caching will store the results of these database queries so that they aren't executed every time a page is requested. Enabling these settings alone can have a big impact on performance, particularly if your pages use a lot of views. This one is kind of a no-brainer.
Boost Module
The Boost module is pretty great. It works very well in tandem with Drupal caching, but it requires some additional configuration. What you end up with after you have the module installed and configured is a caching system that stores the output of your Drupal site as static HTML pages. This takes PHP processing out of the equation, leading to another nice bump in performance.
Memcached
Memcached can speed up dynamic applications (like Drupal) by storing objects in memory. With Boost and Drupal caching, the data being cached is stored on the server's hard drive. With memcached, it's being stored in memory, something that greatly speeds up the response time for a request. Memcached works great in conjunction with both Boost and Drupal caching.
Varnish
Varnish is an HTTP accelerator that, similar to memcached, stores data in memory. It's capable of serving pages much faster than Apache (the most common web server for Drupal sites). It can also be used in conjunction with memcached, although it's often the case that they are not used together and other advanced caching methods are instead implemented alongside Varnish.
Views Caching
Another type of database caching is Views caching. Views is a very popular, but rather resource intensive, Drupal module. Implementing Views caching can give your site a nice additional performance boost by possibly removing a few database queries from the build process.
To set views caching, go to your view. On the right hand side, under Advanced > Other, you'll see a link for Caching. Just go in and set a value - an hour is usually a good default - for each view on your site.
Wrapping Up Part One
Wow, long post and all we've really covered so far is backend performance and caching! This discussion hasn't been comprehensive by any means, but it does provide a great start.
Next time we'll start digging into frontend performance, the area where most of our performance issues reside. What should be obvious so far is that web performance is a subject that is both deep and wide, but also critically important to building successful websites.
If you have any comments about this post, you may politely leave them below.