How we made Portent.com really freaking fast

Cheetah Cub Design & Development

Ian Lurie May 23 2012

Please note: I am not a server expert. This is stuff I figured out by bumbling around, crashing our server and generally wreaking havoc. Be careful, unless you want to see steam coming out of your IT team’s ears.

Cheetah Cub

He can only aspire. Poor little cheetah.

I don’t want to shock anyone, but I’m a little obsessive. And competitive.

No, really, it’s true. I hide it well, I know.

I’ve always obsessed about page performance. Faster pages convert better. They can rank a little bit better. They reduce bounce rates, which can help with PPC quality score. Plus, it just gives folks a much better user experience. Which sounds all squishy and liberal, like me, but separates the decent sites from the oh-my-god-this-site-rocks sites.

So I’d set a goal for Portent.com’s home page: Make it load in 1 second or less. While we aren’t quite there, we’re close. Here’s the Pingdom report, using all of their check locations (including Europe):

pingdom sitespeed report

Site speed report for Portent's home page, via Pingdom

Niiiiice. Even at its slowest, we’re under 2 seconds. That makes me smile. Here’s what my team did, with me micro-managing and driving them basically insane the entire way:

The basics: Images, compression, and code optimization

Site performance is like cycling performance: If you get the fancy stuff and shave your legs, but are in crappy shape, you’ll still ride like, well, me. If you put your site on a content distribution network and invest in speedy servers, but your images are bloated and your code sucks, your site will still drag. So, here’s what we did first:

  1. Put scripts and stylesheets in the ideal order (as much as we could). All external CSS go first. Then include external javascript. That way, most browsers will download CSS in parallel, which gives you a teeny tiny speed boost.
  2. Compressed images. I nearly blew a gasket when I saw we had three-color images that were JPGs (gasp). But, I was calm. I pointed my team to their own image compression post. This reduced bytes transferred by 20%. I walked away, muttering.
  3. Set up (a little) deferred parsing of javascript. This turned out to create some headaches, so we had to backtrack.
  4. Minified CSS, HTML and javascript. Minification is a fancy nonsense word that means ‘remove all comments, spaces and tabs.’ It saved us 2-3 kb per file type, for a total of 6-8 kb. Every little bit helps.
  5. Specified image dimensions for all images. This makes the perceived pageload time a bit faster, as your browser doesn’t have to figure out image sizes.
  6. Turned on server compression. Most popular web servers (Apache and IIS, for example) can automatically compress HTML, CSS, javascript and other files using the GZIP compression algorithm. Which is a fancy way of saying that, by adding one line to our server configuration file, we cut the total transfer size for our home page in half. Not too shabby.

A secret: I used Google Page Speed to come up with all of the changes above. You should, too.

All of this got us down to a 3-4 second page load time.

Was I satisfied? Hell no.

Getting fancier: Expires headers

Getting from 6 to 4 seconds was all we could squeeze out of the basics. Time to get fancier:

We set the ‘expires’ header for some files to a year from now. When you visit a web site, your browser stores or caches lots of files on your hard drive: Stylesheets, images, scripts, etc. That speeds page load time the next time you visit. The server sends those files to your browser with an expires header, which tells your browser when it should re-load them. Our server defaulted to 24 hours for most files and file types.

Not good. Silly, in fact. How often do we change our logo? Or our page background? Once every 1-3 years.

We reconfigured our server to deliver most ‘static’ files with an expires header 1 year in the future.

That shaved another .5 seconds or so off our page loads. We think. We were making a lot of changes at once, so it was hard to tell for certain. But it definitely helped.

Enabled keep-alives

No, this isn’t about killing people who visit our site. It’s about how our web site connects to your browser.

In non-geek, the ‘Keep-Alive’ setting tells the server to hold the connection to your web browser open while you’re browsing our site. That reduces the number of times the server has to open new connections, which saves processor, memory and network overhead.

Time saved? .2 seconds. Your results may vary. When I first turned this on, I set the directive in the configuration file to “Conneption: Keep Alive.” Apache began laughing hysterically at my typing skills, and promptly crashed. Lesson: Computers are literal, but they do have a sense of humor. Check your configuration files carefully.

Dump annoying scripts

We use WordPress. Which is great, 90% of the time. But there are some annoying scripts, like wp-cron.php, that fire every time the server loads a page.

Firing wp-cron every time you load a page is a bit like giving every airline passenger the safety speech as they get on the plane, instead of giving it to everyone all at once. Inefficient. And dumb. We changed it.

Even better, Googlebot somehow found admin-ajax.php and had a grand time crawling it every 30 seconds. That gave our server a huge headache.

We added that to robots.txt. Google stopped crawling it. Life is good again.

Setting up a CDN

We were still seeing slowdowns because of images and other files that transferred sloowwwwlllly for us, and more slowly for folks around the world. The answer: Get our site using a Content Distribution Network, or CDN.

A CDN spreads your files around the internet on special servers. When folks visit your site, they access those files from servers, locations and networks optimized to best deliver them. The result is twofold:

  1. Files arrive faster, because they’re cached and delivered by zippier servers that are (sometimes) closer to the user.
  2. Transfer size shrinks, because content delivered via the CDN is ‘cookieless’. There’s no extra information attached: Just the bits, ma’am.

We tried a few networks. After I nearly hurled my desk to New Jersey in a fit of customer ‘support’ inspired rage, we switched to MaxCDN. They’ve been fantastic for us ever since.

Now our site was getting speedy: Average load time was a hair over 2 seconds. The team probably figured I was done, and they could go back to doing real work. Nooooooo, I had more.

Latency and APC

Our site uses PHP, and we continuously saw high latency. If the ideal server to browser conversation is like this:

BROWSER: Hi server.
SERVER: YO! What’s up?

BROWSER: Can I get the home page for Portent.com?
SERVER: Yep, no problemo, here it is.

Then high latency makes it seem more like this:

BROWSER: Hi server.
SERVER: zzzzzzzz

BROWSER: Server?!
SERVER: zzzzz SNORT cough hey, sorry. What can I do for you?

BROWSER: Can I get the home page for Portent.com?
SERVER: Sure, just a sec, I have it around here somewhere…

BROWSER: ….
SERVER: OK, here you go.

Lots of things cause latency. In our case, the biggest bottleneck was PHP. Every browser visit required the server to execute a bunch of PHP scripts. Which was silly, since most of those scripts did the exact same thing 9 times out of 10.

So, we set up something called Alternative PHP Cache, or APC. APC lets the server cache the results of PHP execution.

I let a real developer handle APC setup, thereby avoiding the whole crash-the-server thing. It went far smoother. The result was like that rocket afterburner thingy on the back of the Batmobile.

Page load times fell to .8-1.5 seconds. I did a happy dance.

What’s next

I’m on a quest, though, and we’re not there yet: I want 80% of the pages on Portent.com loading in 2 seconds or less. And we’re nowhere close:

google analytics page load times

Our page load time report from Google Analytics

That report is from Google Analytics, by the way.

Next steps:

  1. Try optimizing our initial congestion window. By boosting it, we can increase the amount of data delivered to browsers when they first connect to our server.
  2. Find a better way to deliver web fonts. Web fonts are our biggest caching issue right now. Our CDN caused all sorts of problems with them. There are CDNs set up just to deliver web fonts, and we tried them, but they just slowed us down even more. We’re still pondering this one.
  3. Sweep through 1000+ blog posts and re-optimize images. Any volunteers?…

I hope this helps some folks speed up their sites. If you see ideas I missed, let me know, too.

related articles

37 Comments

  1. Anna

    I’ve seen wordpress plugins that automatically compress and replace all your uploaded images FOR you (lossless, yummy!) but I’d have to thoroughly test it before trying it on a live site.

    Of course…that wouldn’t fully compensate for a poorly-optimized image. I ran across one the other day that was 582kb. Nothing fancy, white background with a product photo. I dropped it in photoshop and re-saved it down to 17kb. ’nuff said.

  2. Besides minifying, you can combine your CSS and JavaScript files into one (or as few as possible) apiece. That reduces the overhead spend on headers and file transfer setup.

  3. Hi Ian, great stuff on speeding Portent up. When I saw your original tweet I ran the site through a couple of testing tools, like webpagetest.org and on gtmetrix.com – there’s still some basic large-impact wins you have available (removing duplicate calls to out-dated jQuery scripts, consolidating image HTTP requests etc) that now you’ve caught the speed-bug, you’ll be working on. Another tool you might want to take a look at (if you haven’t already) is zoompf.com.

    • Thanks Mike – I’ll check out zoompf!

  4. Major props! These are great stats! I’m working on an enterprise redesign right now with a new Sitecore CMS and have given IT the “under 1 second load time” requirement. There was no scoffing, so I don’t think they realize how hard it will be. This is certainly some good stuff for them to chew on! =)

    The desktop source code looks great. The smartphone version could use some love. Does WPtouch Pro have settings for that?

    • WPTouch is, well, touchy. We’re trying to figure out why it sometimes goes screwy, but we’re getting there.

      Props to you for the 1 second load time requirement. So tired of sites with 22,000 lines of HTML code.

  5. Ian,

    You could sprite your client logos quite easily.

    How about creating a sprite for your staff head shots used for your recent blog posts. Added benefit, you could re-use the sprite within your blog for a small added benefit.

    Have you looked into one of the WordPress caching plugins like W3 Total Cache or WordPress Super Cache?

    What about investigating putting Varnish or a similar HTTP accelerator in front of WordPress. I’m reasonably sure that W3 Total Cache actually has support for expiring Varnish cache automatically when content is updated in WordPress as well.

    Just a few quick thoughts.

    Al.

  6. SmushIt works well for a multiple compress on WordPress and W3 Total Cache is something I install almost automatically now, yet to try it with a CDN though.

    Good to see speed starting to find some traction, great how those milliseconds add up!

  7. For wordpress, I recommend WP Super Cache plugin (use default aka php caching option, no need to generate pure static files).

    http://wordpress.org/extend/plugins/wp-super-cache/

    You might be surprised how many DB queries are done by theme/wordpres for displaying the page… Also, it handles some other things too.

    It was a life saver when one of the blogs hit 20k uniques traffic per day for a while. And handled custom post types well too.

    • We’re using W3 Total Cache right now. We tried Super Cache and didn’t find the same results, but maybe we should test again.

  8. Everyone loves a page that loads quickly!! It amazes me how many of the large websites that you see could be optimised to load much more effectively.

  9. Jon

    Thank you for writing this! What an honest and needed post–no one else seems to be writing about this important topic–and certainly not in so transparent and helpful a way!

    In addition, I have a tip for you: if you haven’t tried WP Smush.it, you probably should. It will optimize all of those images on all of your blog posts in one fell swoop (I am not an affiliate–I’m just using it on my WP site, and very happy with it–come to think of it, it was gtmetrix that recommended this plugin to me).

    • Jon – I saw that one a few weeks ago, but the wp stats are awful – “2 people say it works, 44 people say it’s broken” – with the latest version of wp. It hasn’t been updated since last November, and none of the forum posts are being answered. The lack of support makes me wary. But it’s on the list to try nonetheless! http://wordpress.org/extend/plugins/cw-image-optimizer/ looked like another possibility.

  10. Ian,

    Have you ever considered using CSS sprites? With them you can drastically cut down on image loads because all or most of the design images load at once.

    • Yeah – we use them for a few things on the site already. Going to add a few more images to the main sprite in the next few weeks.

  11. MAXCDN is such a great tool, and I can’t vouch for it enough. For WordPress sites it’s probably the single most easy thing to do to speed things up.

    Great value.

  12. Andy Schaff

    Andy

    Setting up APC was huge. W3 Total Cache’s disk:enhanced page caching was doing a decent job, but once we got APC setup and had W3 Total Cache using APC, it was night and day. Now on to optimizing the APC config..

    ps. Cheetahs rule

  13. With the advancement in speed have you seen any pick up on other stats like bounce rate off the home page?

    • Bounce rate’s down about 10%. We’re also seeing a higher lead count, but that might also be because of higher rankings in the wake of the merger of our two blogs.

  14. Chris Sherlock

    Have you tried using YSlow?

    • Yep. Got some great data there, too.

    • Yup, we’re looking at deferred initialization as a next step, too. Thanks Mathieu!

  15. James

    Good results!

    You could also look at putting a reverse-proxy in front of your HTTP server, such as varnish.

    What you do is run varnish on port 80 and your web server on another port such as 8080.
    When someone requests a page from your site varnish serves a completely cached copy from RAM, this completely removes the PHP lag.

    • We’ll actually be doing that soon to integrate some of our tools, which run on Python 2.7, into our site, which is on a server that only has Python 2.4 or some such. Thanks!

  16. cryptocompress

    - look @ varnish
    – PHP only time should/can be <150ms

  17. For a lot of that work that you did, you could just have gotten a free CloudFlare account and they do all the HTML/CSS/Image compression for you as well as distribute your content on their CDN. I’m not affiliated with them in any way, I’m just a happy customer.

    • We tried CloudFlare. Never could get it to behave. It wasn’t that much work for us anyway, since compression, etc. was handled by MaxCDN.

  18. It’s worth testing HyperCache as well, btw. In my (extensive, swearing-filled) time attempting to optimise WP before I gave in and just signed up with a managed WP host, I found that Hypercache was usually marginally faster than W3TC.

    The W3TC guys told me that was a configuration issue, to be fair, but it may still be worth a look. Hypercache is also substantially easier to configure.

    Other stuff from the “things I was going to try” list – a lot of people swear by a reverse proxied Nginx frontend on Apache. Mind you, looking at the blog posts on that setup, a lot of people swear *at* it, too. And just replacing Apache with Nginx for WordPress is also highly rated by Those In The Know.

  19. FYI page load time doesn’t entirely depend on your side. The load time comes from the information the browser gives back to Google so it’s mostly on the user side. Besides what you already did (especially with a geographically distributed CDN) there’s not much else you can do.

  20. I loaded your site for the first time and my total load time was 1360ms, however 1020ms was just the initial connection, the assets etc. loaded very very fast, around 300ms.

    I’m on a fast connection (74mbps down) so I suspect my location (England) is the issue, either way your site (if we ignore the entire second it takes to connect) is very very fast.

  21. Matto

    Great tips. I have two more. One, Apache will laugh at you less if you ask it to test the configuration before you restart it. On a production server this means avoiding that terrible downtime as you scramble to find your typos and get the server back up. Run apachectl -t to test your configs. Two, APC is awesome but if misconfigured it’s less effective. Make sure you give it enough RAM. Use the apc.php script that it comes with to see your stats. Your hit percentage should be like 99% after it runs for a bit and fragmentation very low. If it’s the reverse then your set of cached PHP is too big to fit in the cache all at once and you probably need to give it more RAM via php.ini settings.

  22. Try running your image through ScriptPNG and ScriptJPG : http://css-ig.net/

    They optimize (losslessly) pngs and jpgs better than any other tool i’ve seen.

    Using a good tool to do color reduction (lossy of course) before using ScriptPNG is also a good idea. I like to use RIOT : http://luci.criosweb.ro/riot/ or the RIOT plugin for Irfanview to do this. The NeuQuant algorithm it can use does an amazing of reducing color without a noticeable quality loss.

    JPEGmini : http://www.jpegmini.com/ also does an impressive job of compressing jpegs better. The resulting jpeg can be run through ScriptJPG for even further reductions.

  23. You know what the problem with a post like this is? Most of what you said just goes over our heads, and as helpful as it seems to be, only truly technical geeks get it and can do anything about it. Truthfully, the only thing I really understood was the image compression; that’s a shame. lol

  24. This is nice, practical breakdown Ian, well done. As an SEO that spent seven years in the hosting industry, I noticed one key item that’s not on the list -> web server software. Have you looked into Litespeed? (note, I’m not being influenced to endorse them in any way, the product is just awesome).

    http://www.litespeedtech.com/litespeed-vs-apache.html

    No need to spend money on an expensive server. If you have some facet of control over your hosting, you can just use better software. Other sysadmin-focused changes can make a huge difference like MySQL performance tuning, but Litespeed or Nginx alone should typically lead to doubled performance from your web service (shown via the studies in that URL).

    • We’re actually looking at Nginx, as well as potential reverse proxy and/or Varnish.

  25. Jasper

    Hi,
    Can anyone tell me the difference between using Max CDN and CloudFlare?? Cloud Flare also has a CDN technology, but i don’t know if they have better or more servers attached to their service or Max CDN has more??

    Also, aside from CDN service that i don’t have, i almost have all the optimization like APC, GZip, and things liks that for my server/website, but my site is still running slow. Can someone help me speed up my site?? It seems like as time goes by that the site becomes slower. The first byte time is the culprit because it takes about 3-5seconds before it starts loading the site or page.

Comments are closed.