Category Archives: Performance

Pragmatic Bookshelf Website Performance

I’ve been a big fan of the Pragmatic Bookshelf series, in particular their monthly online magazine. The magazine are downloadable in PDF, .mobi, and .epub formats, and browsable online in HTML format.

Browsing through the latest couple of issues, I noticed a distinct slowness as some of the images were downloaded. This is usually a hint that a high resolution image is being referenced, but being “cropped” down to a smaller size with the height/width attributes in the HTML. For example, see this story about Ruby Bundler and look at the red ribbon image. The source image is 693×693 but is being displayed as 190×190. It’s also a very high quality level and weighs in at 203KB – compare with the page itself which is only about 10KB. Resizing this JPEG image in PhotoShop dropped the size down to 6KB (or 3KB at medium quality), with no visible difference on the web page.

With those possible savings, I looked closer at the rest of the Magazines pages to see what other performance improvements could be gained, following “best practices” advice from tools like YSlow, PageSpeed, and WebPageTest.org. Rather than trying to solve everything at once, I’ve suggested improvements in priority order. I’ve also focused on content served via pragprog.com because that will be the easiest to change. The 3rd-party widgets like Digg and Reddit can be dealt with later, if at all. (Performance improvements on 3rd-party widgets usually need to come from the 3rd-party itself.)

Step 1: Images Sizes

As a first step, update the publishing process to reduce image sizes required in all page downloads. Specific changes:

  • Re-size images correctly for their use on the page (i.e., don’t re-size via HTML height/width)
  • For JPEG images, save at the lowest quality that still looks good (e.g., Medium or 50)
  • For PNG images, convert to 8-bit if quality is acceptable
  • Run YSlow Smush.it (lossless compression) on all images and switch to the compressed versions
  • Switch GIF to PNG where Smush.it recommends (typically for very small images, excludes any using alpha transparency)

Step 2: Image Expiration and Hosting

Continuing to improve the image delivery, there are a couple of specific changes that can help here:

  • Add “expires” settings for images – at least a week, but preferably a “far future” expiration date with version increments in the filename (header_v1.jpg, header_v2.jpg, etc.)
  • Move images currently served on pragprog.com to one of the assetsN.pragprog.com or sharedN.pragprog.com domains (which do have image expiration set correctly); pragprog.com also seems to be a bit slower when serving images

Step 3: Better Handling of CSS and JavaScript

On the CSS/JS side, there is some room for improvement in the number and size of these static files:

  • Reorganize and combine the CSS files, removing the use of “@import” as well; currently there are 7 unique CSS files for the core page design (i.e., not counting 3rd-party widgets). These could be combined with the use of integrated media selectors rather than having multiple entries
  • Minify CSS and JavaScript (e.g., using YUICompressor)
  • Add versioning to CSS/JS files and set a far-future expires time

Step 4: Miscellaneous

Finally, here are some additional fine-tuning adjustments that will also help:

  • Confirm whether or not store.js is needed on all pages – remove if not
  • Convert images in page templates to use CSS Sprites
  • Switch Google Analytics to load asynchronously and include JS file at page bottom
  • Change source of diggthis.js from digg.com to widgets.digg.com to avoid extra redirect
  • Change source of button.js from reddit.com to to www.reddit.com to avoid extra redirect

Hopefully the above list gives a good roadmap for the improvements that can be made on a site like this. Most of this hopefully doesn’t require very significant changes to their build process, but should give dramatic improvements for site visitors.

Performance Makeover: Cantoni.org

After my team launched a new site design and blog system for the Yahoo! Developer Network, I decided to review the performance of this site to see where it could be improved. In summary, after removing one performance-hogging widget and following recommendations from YSlow and Page Speed, the site should be running much faster now.

This site is running on a shared web host from Pair Networks and is powered by Movable Type. It’s not a very complicated site, but is a good illustration of the improvements possible by following web performance best practices.

My first step was to run the home page through WebPageTest to get a good overview of the problem spots. I was surprised to see about 60 JavaScript and image requests just for the Lijit search widget! On the plus side, they do have expires times set for the images, and no cookies are going back to the lijit.com domain, but this is still a ton of content to be loaded for the first-time viewer. Based on these numbers, and the fact that I was just experimenting with it, my first step was to remove the Lijit widget.

After removing the Lijit widget, the numbers improved dramatically:

Measure Original After Remove Lijit Improvement
YSlow 78 83 6%
Page Speed 74 83 12%
Requests 59 17 71%
Size (KB) 257 173 33%
Doc Complete (sec) 4.0 1.88 53%

With the big piece out of the way, now I could focus on the remaining issues, uses YSlow, Page Speed, and WebPageTest.org as my guides. I implemented a series of improvements:

  • Removed Mint tracking; the Mint UI looks cool, but this is redundant with Google Analytics which I’m already using
  • Removed Yahoo! Buzz badge; I don’t think anyone ever “buzzed” one of my stories so this isn’t needed
  • Added gzip compression for text files (HTML, CSS, JavaScript) served off my domain; I didn’t realize that my host provider had mod_deflate installed, so I was able to configure it via .htaccess files
  • Reduced image size by converting PNG files to 8-bit, and then running everything through SmushIt
  • Changed Google Analytics to use the asynchronous version
  • Merged separate print CSS into the main stylesheet, using “@media print” designators
  • Modified my CSS/JavaScript combo handler to include Last-Modifed and Vary headers in the response, for improved cacheability
  • Minified JavaScript using YUI Compressor
  • Minified CSS using cssmin.js
  • Moved images from cantoni.org to Amazon S3 hosting

After all of the above, the results compared to the original were pretty good:

Measure Original Perf Changes
& Remove Lijit
Improvement
YSlow 78 96 23%
Page Speed 74 97 31%
Requests 59 14 70%
Size (KB) 257 77 70%
Doc Complete (s) 4.0 1.28 68%

Observations and further things to investigate:

  • Google Ads still drag down the page grades a bit, but don’t have a huge impact on page load time so I’m leaving them in for now; I’m only running ads on individual entries now, not on the home page
  • WebPageTest helped me understand lossy optimizations beyond SmushIt; for example converting 24-bit PNG to 8-bit, and saving JPEG with lower quality level
  • I tried using YUI Compressor to minimize my CSS, but it broke the site layout slightly, so need to investigate this further
  • One of the Page Speed recommendations is to minify the HTML; I tried that manually and found about 5% further reduction in delivered file size, but it’s not easy to implement on the dynamically-built Movable Type pages so will ignore that rule for now
  • The images are on Amazon S3, but not yet hosted via Cloud Front which is a true CDN; I plan to do some testing with this both ways to see how much it helps
  • I’d like to work S3 and SmushIt into Movable Type workflow, hopefully in a plugin

Overall this quick makeover was a good illustration of the available performance tools. Like any optimization, you need to make sure to measure first to identify the slow spots. I would also suggest not blindly following every recommendation, but aim to solve things in the proper way for your own environment.