Saturday, June 4, 2011

Site Speed For Dummies Part 2 – How To Do It

Let me first apologise for the size of this post. It’s massive, but learning ain’t easy. A lot of this does get pretty techy, and you may have to accept that you just can’t do some of the stuff unless you’re a developer. So to make this post as actionable as possible, I wanted people to know what things are achievable for them, based on their knowledge and ability. For this reason I developed an extremely sophisticated algorithm that will automatically let you know which stuff you can do and what you will get the highest ROI from. Without further adieu, I give you “The Dummy Scale”:

This little guy means that almost anyone should be capable of doing the task. It involves mostly copy and paste and will give you the tasks you can do with the least amount of time. Examples would be installing analytics code.

Next up is this guy with the sticky up hair. He’s not quite as simple as the previous character, so if you have a little bit of knowledge of code you should be able to handle it.

Lastly, this guy has glasses: need I say more? This stuff is pretty heavy-handed. Don’t go near these ones without at least six cans of Red Bull and a couple of all-nighters planned. OK, it’s not that bad, but they do involve things like the .htaccess file, which I wouldn’t recommend going near unless you know what you’re doing!

OK, let’s get cracking…

I’m going to run through an example, use some tools that Google recommends and see what the outcome is. Once I have a list of recommendations from the tools I’m going to talk through actually implementing them.

I have picked three sites that are all in the same (kind of) market. The three sites are:

Compare Site Speed

Step 1

To compare site speed, I used a great tool at http://www.webpagetest.org which allows you to add a URL and time how long it takes to load the page. What’s cool, though, is that it allows you to compare multiple sites side-by-side. Once a site is fully loaded, the screen goes grey to help easily identify which sites load first and last. So have a look at the video below comparing the three sites:

  1. WHSmith with a load time of 9.9 seconds
  2. Waterstones at 10.3 seconds
  3. Penguin with a whopping 31.4 seconds

To be clear, even though it won, WHSmith is by no means the Usain Bolt of the internet. Amazon, for example, renders in a cool 4.4 seconds! So what can we do about this? Let’s analyse each of them using some cool tools.

Step 2

Download Google’s Page Speed tool: http://code.google.com/speed/page-speed/

Step 3

Go to the site you want to analyse. In this case, we’ll look at Penguin. Open Page Speed and click Analyse. You will then get an output that looks something like this:

Woo-hoo! All you need to do now is use efficient CSS selectors, combine images into CSS sprites and enable compression! Ehh… what?! If you are like me, that means nothing to you. I don’t know how to do a single thing on that list. But I’m going to find out how.

So in no particular order….

Use Efficient CSS Selectors

This took me a while to get my head around, so I’ll try to explain it the best I can. Apparently, when you load a page, the browser scans that page looking for information that it can put into a tree-shaped diagram. This is known as an “internal document tree” and looks like this:

This helps the browser break the page down into its simplest elements and organise them in a way it can read. Reading the image above, we can see that on this page there is a body element and within that there are another two elements, the <H1> and the <P>. Then under each of those there is an <em> element.

Now let’s assume that I tell you I want to make the words in the <em> element within <P> red. If you write the code: Em {colour : blue} not only would it make the <P> <em> blue, but it would also make the <em> element under the <h1> blue, as well as any other <em> elements on that page. In order to select only the <em> under <p>, I would need to write: p em {colour : blue}. That would only colour the <em> element in the <p> area. What we have just done is written a descendant selector.

Put simply, a descendant selector means isolating one element within another element. This is done most efficiently when you don’t make the browser keep looking for something when it’s already found it. To be honest, though, it’s pretty techy, and unless you’re a developer, you’re not going to be able to correct your code. This site explains the process pretty well.

Prefer Asynchronous Resources

Doing things “asynchronously” is a strange concept. You would think that in order to make your site load quicker, you’d want to do as many tasks as possible at once, so the page could load faster. Although multi-tasking generally makes things happen faster, when it comes to loading a web page, the more things done at the same time actually slows you down. It’s much better to load pages asynchronously, simply means not doing things at the same time.

Doing things asynchronously allows you to prioritise the items which you would like to load first. When opening a new page, the only information you need to load immediately is the information that’s above the fold. The rest of the stuff isn’t visible to the user until they scroll down, so it makes sense that the priority should be given to making the stuff above the fold load first. Likewise, some items like tracking scripts are never visible to the user anyway, so it would make sense to prioritise all visible content ahead of that.

So our original Penguin site speed report shows two items which should be changed:

The image above shows that the Facebook info and the Google Analytics could be changed to load asynchronously and allow the rest of the page to load more quickly. The Analytics one is an easy win: all they need to do is update the code to the latest Analytics code, and it will be asynchronous. As for the Facebook part, you would need to go the Google-suggested route and use a script DOM element.

Get Site Speed Stats In Google Analytics

This doesn’t speed your site up, but the news broke as I was researching this post, so I thought it was best to include it (plus it’s really easy to do). It’s possible to get site speed tracking data straight from within your Google Analytics account.

  • Step 1 – Install the latest version of the Google analytics asynchronous code on your site.
  • Step 2 – Add the line: “_gaq.push(['_trackPageLoadTime'])” to your analytics code.
  • Step 3 – Enjoy all your new juicy data.

Specify Image Sizes

This one is nice and simple and actually makes sense. When loading a page with no image dimensions in the source code, the browser needs to guess where to put everything else around that image until it’s finished downloading. Then when the image does download, it needs to go back and do reflows and repaints (kind of like loading it again) and place it at the correct size and reshuffle the page to make it fit.

If, however, you specify image dimensions, the browser doesn’t have this problem. It’s kind of like saving a seat for your mate in a really busy pub. When he finally gets to the pub, he already knows where his seat is and can go straight to the bar and get a nice cold beer! Mmmm, beer!

OK, so how can we get these poor images on the Penguin site some cold beer? Let’s look at the current page and source code for one of the images.

One of the images that the test highlighted as not having dimensions was the image of Jeremy Clarkson. So let’s look at the source code for it.

<a href=”http://itunes.apple.com/gb/app/iclarkson/id406162322?mt=8″ alt=”iClarkson” title=”iClarkson” target=”_blank”><img src=”http://www.penguin.co.uk/static/cs/uk/0/penguin_homepage/images/0311/panel_03.3_bg.jpg” height=”81″ alt=”" border=”0″ /></a>

The highlighted part above shows that the image height is specified but not the width. This is an easy fix and just needs a small tweak as shown below.

<a href=”http://itunes.apple.com/gb/app/iclarkson/id406162322?mt=8″ alt=”iClarkson” title=”iClarkson” target=”_blank”><img src=”http://www.penguin.co.uk/static/cs/uk/0/penguin_homepage/images/0311/panel_03.3_bg.jpg” width= “67” height=”81″ alt=”" border=”0″ /></a>

Can you taste that beer?

Obviously, this is a really simple example, and to do all the images on a site the size of Penguin’s would take a long time, but it does show these things should just be done right at the start.

One more thing to note is not to resize images on the fly. If, for example, we wanted a large version of Mr Clarkson’s face (don’t know why), it’s not best practice to simply scale up the numbers in the highlighted section above. Instead, use an image editing software to adjust the image to the size you want and then save that version.

Combine Images into CSS Sprites

Let me start by explaining when sprites are useful, as this will help the explanation later seem easier. Social media buttons are a good example of this. Lots of social media buttons are animated, meaning when you hover over them they do something, they might light up, move, get bigger, etc. This is mainly done to let you know you can interact with the object.

Whatever they do, this is achieved by having two separate images. One shows when you are not pointing at it, then another image shows when you hover over it. Think of it like the little flip animations you used to make as a kid:

By changing quickly between all the images in the flip book, it gives the appearance of character movement, and the same thing happens with lots of hover features. The trouble with this is that it uses lots of images (if you’ve ever drawn one of these books, you know how much of a pain it is drawing 50 images that are pretty much identical). Well, to put it simply, browsers can’t be bothered requesting all these pictures from different places, either. Fifty images means fifty URLs that the browser needs to go to and pull that image from, and that takes time!

The whole purpose of sprites is based around the 80/20 rule of optimisation. Apparently the majority of time spent rendering a page is not down to downloading the image. The main cause of slow rendering is excessive HTTP requests. In other words, stop referencing so many places to pull images from. Sprites solve this problem because instead of having 10 images with 10 separate locations, you combine those images into one big image using a sprite, and then just reference the part of the image which you want to show at that particular location or time.

So sprites are created by ripping all the pages out the flick book and sticking them to one big sheet of paper in an organised order. This then becomes one big page instead of 50 individual ones. Now the browser only needs to go to one URL to get all the images.

So how does this actually work? Well, you tell the browser which part of the bigger image to show by referencing an area of pixels. A really basic example would be changing the colour of a square when you hovered over it. Look at the three images below.

If you wanted to make this change from red to blue without using sprites, you would need to request two different URLs. You would tell the browser that by default, it should show the image “http://www.mydomain.com/red-image”, then when someone hovers over it, show the image “http://www.mydomain.com/blue-image”.This causes two HTTP requests.

If, however, you want to use sprites, you’d create the bigger rectangle image, which is the two smaller ones stuck together with one pixel gap. You would then tell the browser grab the image URL “http://www.mydomain.com/new-bigger-image” but only show pixels “0 to 50” x 50 (the red part) as a default. But when someone hovers over the image, you would tell the browser to show pixels “52 to 101” x 50 (the blue part). This means that while the total number of pixels is only slightly increased, the requests have been reduced from 2 to 1. Obviously, this is a very simplistic example, but if you do this across a whole site with lots of images, it can make a considerable difference. Check out one of Amazon’s sprites for example:

Doing this can be difficult, but thankfully the tool which Google suggests, SpriteMe, is really good at talking you through the process. Sprites can seem counter-intuitive because logic tells you that making big images slows pages down, but based on reducing the number of requests from say 10 to 1, the benefits of the reduced calls outweigh any increases in the image size.

Leveraging Browser Caching

Thank God for something that was easy to understand. Learning most of this has been a challenge, so when I saw this it made me smile. While easy to understand, it’s not too easy to do, so it’s mega geeks only for this one, I’m afraid. Like previously mentioned, making lots of requests to external sources – whether its images, CSS, JavaScript – takes time, and if they can be reduced or avoided, it can only speed your site up.

Browser caching is great for doing this, and I have to say it is one of the quickest wins I’ve seen so far. Essentially, leveraging browser caching is a cross between giving your browser a better memory and a camera. If there was no browser cache, then every time you went to a website, you would need to download everything again. Thankfully, that’s not the case. There are ways to make your browsers memory last longer. Most sites have a lot of content that either never changes or very rarely changes. It therefore doesn’t make sense to keep making your browser download the same stuff time and time again. Instead, if you know what items on your site are not going to change for, say, a year, you can tell browsers to remember things the way they are now until a year’s time.

This means that for the next year, instead of downloading stuff, the first time you visit that site those items are stored locally in the browser cache and allows the browser to load the page much quicker.

This isn’t suitable for all sites, of course. e-Commerce sites, for example, have a lot of changing products. So if you are going to be updating the product range regularly, it’s perhaps not worth your while to set the browser cache to a year, though certainly setting it to a month can help. This is probably most likely why the Penguin site does so badly in this area: the site is updated quite regularly with new books and special offers.

To actually do this, you need to use the .htaccess file. Unless you know what you’re doing, I would recommend getting a developer to do this. There is a post here on how to do it, but read the comments at the bottom as some people had some issues with this method. I could write the code out, but I’d just be repeating what’s on that post.

Combine External JavaScript

The theory of combining JavaScript is the same as using sprites. The point is to reduce the number of calls that the browser needs to make to external sources. In this case, it’s JS files rather than images, but the idea is the same. Rather than calling lots of different JS files, let’s just put all the JS code together into one file and reference the correct part for the job.

Points to note – sometimes JS need to be completed in a certain order, so don’t just throw it all together willy-nilly. Look at the page you are optimising, and take a note of the order of the JS files and the location. This should be used as the order in which to paste the code into the new document. So let’s see an example. If we look at the Penguin site again, one of the recommendations is:

So first, we had better make sure this is the order in which they are loaded. To do this, view the source (Ctrl+U) then find (Ctrl+F) and search for “gettopup”.

By searching I have found the order of the JS is slightly different:

I also can’t seem to find the file that ends in “/jquery/all.js”. But for the purposes of this example, let’s assume it’s a perfect world. We could then create a new document in a text editor and call it something like “newjsdocument.js”. Then we would paste the JS code (in the correct order) into that document, save it and re-upload it. Now any time the other documents are referenced, the browser will refer to the one document instead of three or four.

Additional notes to consider

  1. Always make copies of your JS code before you go mixing it up.
  2. If you use JS resources that are constantly changing, this may not be applicable.
  3. Many times there are good reasons for having separate JS files, none of which I understand, but I’m told they are good enough reasons.
  4. Additional savings can also be made by minifying the new big JS document (just about to explain what this means).

Minifying CSS

Minifying in general is good practice. When websites are written using CSS, the actual CSS document can be pretty large. Depending how fancy the site styling is, there can be thousands of lines of code. Unlike people, browsers don’t need text to be spaced out nicely and formatted in an easy-to-read and user-friendly manner. If the code is correct, it can all be jammed together by removing unnecessary spacing and commas. To use this blog post as an example, how much space do you think would be saved if I didn’t use spaces, commas, line breaks, etc.? The answer is lots. When it comes to code, Space = Speed.

According to the Firebug speed test, sites could save 20% on load times by minifying CSS files. That’s pretty cool for something that’s really easy to do. So how do you do it? Well, thankfully some clever people have made quite a lot of tools that are really easy to use and do the work for you. All you need to do is paste your code into them, hit the Compress button, save the output in a new document and upload it.

A word of warning: if you minify CSS and then want to change anything in the CSS file later, it can be very hard to find the correct parts you need. Always make a nice, easy to work on version before the compression is done. That way, if you ever need to make any other changes, all you need to do is use the saved version and make a new compressed copy! A good tool for doing this is http://www.csscompressor.com/.

Enable Compression

Enabling compression is one of my favourite optimisation tips, not least because it’s one of the easiest to understand, though admittedly it’s not the easiest to implement unless you know what you’re doing. Enabling compression pretty much works the same as regular compression on your computer. If you have lots of files to email someone, you could attach them one by one and clog up your poor mate’s email inbox, or you could put them all in a folder, zip them up and send it as one small file.

In web design this can be done by the servers. It should be noted that if the user doesn’t have this enabled on their browser or are using a really old browser, this won’t work. To be honest, though, most modern browsers today do support it, so I wouldn’t worry so much.

So if it’s done at server side, what do we need to actually do to speed our site up? We need to tell the server to send the compressed version if the user’s browser supports it. This is done in the .htaccess file again. I would strongly advise against going anywhere near your .htaccess file unless you really know your stuff, as it’s easily the fastest way to ruin your site. In the interest of not adding on another 1000 words to the blog post, I won’t go into the hairy details, but enabling compression is definitely into Dev territory. This post covers it in more detail if you want to know more.

There are definitely big gains to be had by enabling compression so if you have a developer it should be top of your to do list. The firebug plug-in for our Penguin example shows that a 426.7KiB (75% reduction) in transfer size could be achieved by enabling compression, and that would be a huge win

Minimize DNS Lookups

Although they are separate items on the list, I thought I would talk about minimising DNS lookups and parallelising downloads across hostnames together because there are conflicting arguments to each.

Let me explain minimising DNS lookups first. DNS stands for Domain Name Servers, and they work like the phone book. When you tell a browser to go to www.mydomain.com, the browser essentially uses a kind of phone book to look up your domain. Beside your domain will be the DNS code/number, which gives the browser the location of the files on that domain. Looking up those numbers takes time, so the more sites that you need to look up, the longer it takes. Doesn’t that sound much simpler than ‘minimise DNS lookup’? #DummiesFTW!

So when the speed tip says “minimise the number of DNS lookups”, it essentially means try to limit the number of different websites you list. So if your website requests information from four different URLs like:

That would be a total of three DNS lookups. Why not four? Because, http://twitter.com/ and http://twitter.com/#!/CraigBradford have the same DNS. Anything on the same domain has the same DNS. Easy, right?

So when would you request information from URLs? If you want to pull in style sheets, JS, social API data, those are all DNS lookups. So how do we minimise the number of DNS lookups? Well, the recommendations I’ve read are to essentially do either of the following:

  1. Anything that’s on a sub-domain, change to a directory. In other words, if you reference “something.mywebsite.com”, change it to www.mywebsite.com/something. This is confusing because it’s still on the same domain, so it shouldn’t be an extra DNS lookup, right? Wrong. Apparently the browsers treat these as separate lookups, even though they are not.
  2. If you are pulling in stuff from several websites, anything that can be put onto the same domain should be. This would be applicable if you had lots of images getting pulled from different sources. If you could stick them all on the one site (the same DNS), like Flickr for example (*wink wink), you have just limited the number of images being hosted on your site and also reduced the number of DNS lookups.

The following example is completely unrealistic but makes it easy to understand. Let’s say you have an e-commerce site with 1000 images on it. But because you’re slightly cheap and dodgy, you just use other people images from a thousand different sites. That means that when loading your huge page, the browser needs to go do 1000 DNS lookups. But if, however, you set up a Flickr account and hosted all your items there, you would only have 1 DNS lookup as every picture would be Flickr.com/image1, Flickr.com/image2, etc.

So if that’s the case, why doesn’t everyone just put all images on Flickr? Well, that brings me to parallelising downloads across hostnames. As you probably guessed from the name, it has something to do with doing things in parallel.

Parallelise downloads across Hostnames

When your browser loads a page, it looks at all the files it needs to download and then the number of places it needs to get those things from. To use the example above, let’s say your page lists:

  • 20 Facebook profile pages
  • 20 Twitter profile pages
  • 20 YouTube videos
  • 20 images from Flickr

At this point, the browser does some quick sums and says I have 80 files to download, but there are four places I can get them from, so I need to get 20 from each! Now comes the catch. Most browsers only allow 2 connections to any one host (DNS) at one time. So for the browser to download the 20 files it would need to do 2 at a time and put the rest in a queue. TSo there would be four queues of 20. From this it’s clear to see why hosting 1000 images on Flickr wouldn’t be a good idea as it would be a huge big queue.

This is where the idea of parallelising downloads across hostnames comes in. I think I’ll compare this to toilets at music festivals….

If there are 80 people waiting to go to the toilet and there is only one toilet and these festival goers don’t mind going two at a time, then it would take 40 toilet sessions to clear the queue. If there are 4 toilets and again people don’t mind sharing, it would only take 10 toilet sessions to clear the queue. So it’s easy to see the advantage having more than one toilet (host). Common sense really, once you get past all the jargon. This is where browsers thinking that a sub-domain is a different DNS can be useful. By hosting items of “something.mydomain.com” instead of “mydomain.com/something” you have given the browser an extra toilet to reduce the queue. Just in case I didn’t explain the toilet metaphor correctly, the queue of people represent the time it takes to download the page, so you could consider each person as a second if you like.

I hope you can see the conflict of interest here; I literally just corrected myself from the previous recommendation. Here is a breakdown of the pros and cons of each.

Minimize DNS Lookups

  • Advantage – Speeds up page by reducing the time it takes to find all files.
  • Disadvantage – Increases the bandwidth on each location, so if there are loads of files, it can make a queue, which can actually slow your page down even more.

Parallelise downloads across Hostnames

  • Advantages – Reduces queues at each of the file sources, spreads the bandwidth load
  • Disadvantages – Increases the number of DNS lookups.

This is a balancing act and is down to the number of files on any page. Doing either one of these to an extreme will likely slow down your site, as it would have a negative effect on the other. To use another extreme example, if you had only four files it doesn’t make sense to make two subdomains. Assuming these files are not massive, you wouldn’t stand to gain very much. Where this becomes useful I think is more when it comes to using JavaScript and ordering the way your page loads.

“A lot of site speed comes down to setting priorities.”

A page fully loading and the user perceiving the page as fully loaded are two different things. If you have a lot of images, for example, it is really obvious to the user if there are big gaps all over the page. Therefore it might be worthwhile putting the images which are above the fold in a short queue to make sure that the first thing the user sees when they land on the page at least looks like a fully loaded page. The rest, meanwhile, can load below the fold. From my research, a lot of page speed comes down to setting priorities.

If I had to pick one to focus on, I would recommend parallelising downloads as you stand to gain the most if you do correctly.

Conclusion:

I started this series in the hope of being able to make speed optimisation a realistic and achievable goal for almost anyone with little web or code expertise. The reality is that this should really be left to the clever guys. Undoubtedly some of you will finish reading this and feel that a lot of it is still unachievable (myself included), but I hope there are enough quick wins that you feel you can achieve something and have at least learned the areas that you will require assistance in achieving. By learning about the tasks above, it also allows you to delegate the tasks to developers without them saying they can’t do it because it will take them two years to complete. So if anything, you can at least be in a knowledgeable position to outsource.

So what is the take away from site speed?

1- Optimising for site speed should not be a priority. Unless you are a big site, the ROI will be pretty low. Only have developers working on it if they have nothing else to do.

2- A lot of the recommended tweaks that the software suggests will not be suitable for every site. Often there are reasons why things are that way, and it’s best to leave them the way they are. What you gain on one thing could have a negative effect on others.

3- New sites should get this stuff right at the start. It’s easier to do it correctly the first time than go back and pick out tiny pieces of code.

4- Always make copies of all code before making changes. This makes updating much easier.

5- Speed is a project, not a task, so plan to make the changes over time and do them in order of gains. Also keep in mind the consequences of any changes.

6- Lastly, my little bit of wisdom for the day would be, if you want to learn something, teach it to others; it’s the best way to learn.

I hope this post has made a very techy subject actionable for some people. The plan was to have a third part, but I really don’t feel it’s necessary. If you have a big site, the examples in Part 1 speak from themselves. For big sites, there are big wins; for smaller sites, put it on your to do someday list. Thanks for reading, feel free to shoot me questions and comments and I’ll help where possible. You can also get Craig on Twitter: @CraigBradford

No comments:

Post a Comment

Disqus for ully's online marketing

Disqus for ully's online marketing