6 Steps to identify the major web site performance problems on pages like masters.com

Remark: The analysis in this blog was done on masters.com on March 24th 2010. By April 2nd 2010 masters.com was re-launched with a new look and feel. Some of the problems highlighted in this blog are still on the re-launched site. I will publish another blog analyzing the current site, compare it with the old one and highlight the changes. ALL the highlighted problems in this blog are however often seen and therefore I hope you enjoy and learn from this blog. Here we go …

It used to be that the only people who would tune in for the Masters were readers of Golf Digest. This year, however, you can add to that base audience the readers of People, InTouch, and even the National Enquirer. While Tiger Woods may not appreciate all the increased attention, it can only help boost ratings for the Masters itself. The problem is that if all those viewers try to visit www.masters.com, they might find themselves waiting a long time to see if Elin turns up.

In order to understand some of the issues that might come up this week – even before Tiger takes the first tee – I did an analysis of www.masters.com. Like earlier analyses I did for vancouver2010.com and utah.travel, I want to show you how to analyze a popular site like masters.com, and highlight potential problems based on my experience and web site performance best practices like those from Yahoo and Google

Step 1: Define and Record the Use Case

Performance Analysis should always be done on all different types of popular browsers. I recommend using the Dynatrace AJAX Edition for Internet Explorer, YSlow & PageSpeed for FireFox and SpeedTracer for Chrome. If there are “fundamental” issues on the web site you will find most of them in every browser: however, there definitely are specific problems that only happen in Internet Explorer – due to the nature of this browser like having a slower JavaScript engine than other browsers, not having native support for getElementsByClassName, …I use the Free Dynatrace AJAX Edition for my analysis. It works on IE 6, 7 & 8 and provides some features that other tools in other browsers don’t support, e.g.: full tracing of JavaScript, DOM access, XHR calls, network and rendering activity. Before I start I make sure that my browser’s cache is cleared as I want to focus on network download times in my first run. I can do this manually via the Internet Options dialog in IE or I can let the AJAX Edition clear the cache for me before I start tracing (it is an option in the Run Configuration). Now I go ahead and start tracing the following use case:

  • go to http://masters.com (I leave the www out of the URL to also see how much overhead the redirect will create)
  • I check out who the 2010 Tournament Invitees are
  • Click through the individual menu items like News & Photos, The Course, …
  • On the players page I select Tiger Woods to see his Bio
  • Go the Leader Board to check out the latest scores and play with the Font Size Adjustment option (to make the font bigger)

Step 2: The first page load time is the most important one

If you go to a website the load time of the initial page decides whether you keep browsing or not. If it takes 10 seconds to display anything on the page or even longer for the site to become interactive you probably won’t be happy with the browsing experience. If the page comes up immediately, you are more willing to spend more time on the page as you get what you want fast without losing too much time waiting.  Consecutive visits to that page should also be faster than the first time visit as images, javascript files, … can be cached locally on the client. Let’s start with the Summary View on the home page of masters.com:

Summary View of masters.com page showing high network time and many embedded objects
Summary View of masters.com page showing high network time and many embedded objects

The following observations can be made on that page by looking at the data shown in the Summary View:

  • It takes almost 10 seconds till the onLoad event is triggered. The onLoad event is triggered when the initial HTML document and all embedded resources are downloaded
  • It takes 3 seconds till the first drawing activity -> the user sees a blank white page before the browser starts rendering some of the images
  • 23 JavaScript files and 99 Images are on that page -> some of these files can potentially be merged to reduce roundtrips
  • 6 XHR Requests are made to retrieve dynamic content prior to the onLoad event -> Can these be delayed? Can these be merged into fewer calls?
  • We have high server network time – some of this time is influenced by network latency but it still seems that the servers are pretty busy delivering the (mainly) static content.
  • Although there is not too much time spent in JavaScript – most is spent in the script tag execution -> we have 23 JavaScript files – each of these need to be parsed and executed

Step 3: Can we speed up downloading all these resources?

Drilling into the TimeLine view reveals where these resources come from and what happens on that page over time:

TimeLine View showing that all resources come from the same network domain
TimeLine View showing that all resources come from the same network domain

The following observations can be made by looking at the network downloads, JavaScript executions, Rendering activity and events like XHR and onLoad:

  • The redirect from masters.com to www.masters.com takes almost 500ms
  • There is another redirect from www.masters.com to www.masters.com/en_us/index.html taking almost 400ms -> one of these redirects would be sufficient as masters.com could directly redirect to the final index.html page saving 500ms
  • All network resources are delivered from a single domain limiting the user to download more resources in parallel -> use the concept of Domain Sharding to allow the browser to use more physical connections in order to download more resources at the same time. Adding a second domain would for instance reduce the time to download all content by roughly 50%.
  • Some JavaScript files are downloaded in the very beginning -> a Best Practice from Yahoo & Google is to move scripts to the bottom of your HTML Document

The other thing that we want to look into is whether it is an option to merge JavaScript, CSS or Image Files. As seen from the Summary View and also from the TimeLine View this page includes 3 CSS files, 23 JavaScript files and 99 Images. Both Google and Yahoo have a section on how to minimize round-trip times and the number of roundtrips by merging multiple CSS and JavaScript files. As for images: there is a technique called CSS Sprites that merges static images into a single image.

Step 4: How good is my 2nd visit experience?

In order to see how local caching is used I can go ahead and analyze the HTTP headers for cache-control settings. In order to get a quick overview I simply record another Dynatrace AJAX Session browsing to the masters.com homepage. This time I don’t clear my cache as I want to test how many requests come from the cache and which ones are still downloaded from the network:

All JavaScript and some images are still downloaded from the Network
All JavaScript and some images are still downloaded from the Network

The Summary View shows us that 3 CSS, 23 JavaScript and 18 Images are still downloaded from the Network. A double click on the JavaScript block in the Chart opens the Network View with all these JavaScript files that were downloaded from the network:

Network View showing that JavaScript files have a very short cache-control setting
Network View showing that JavaScript files have a very short cache-control setting

The reason why these JavaScript files are downloaded from the server instead of being retrieved from the cache is not a missing cache-control setting. It is due to a very short value for max-age. It is set to 800s. Unless I browse to the page within 800 seconds I will always retrieve the content from the web server. I assume that most of these JavaScript files won’t really change that frequently. The same holds true for the CSS and Images files. These have the max-age header set – but just not far ahead in the future:

Images and CSS files not cached long enough
Images and CSS files not cached long enough

To solve this problem it is recommended to use far-future expires headers. Check out the RFC for Cache Control as well as the Best Practices on this topic by Yahoo and Google. Unless there is a reason to constantly download these files (in case they really frequently change) it is better to leverage the local browser cache and reduce download times.

Step 5: AJAX for any price?

Retrieving asynchronous content from the server and then displaying this content by manipulating the page is a great thing and enables many of the great features we see in Web 2.0 applications. But – there are also use cases where retrieving certain information via an asynchronous channel doesn’t necessarily improve the end-user experience.In the TimeLine view we can see 6 different XHR (XmlHttpRequest) calls retrieving content from the server triggered by JavaScript files that were downloaded. A double click on the first XHR request brings me to the JavaScript trace and shows me a) who executed the XHR call b) what content was retrieved and c) what was done with the response:

Using XHR to retrieve title for DIV tag. Overkill of using AJAX?
Using XHR to retrieve title for DIV tag. Overkill of using AJAX?

The PurePath shows us the following information:

  • messages.js makes the XHR request to retrieve messages.xml
  • The retrieved content is an XML document containing a messageText element with the text “The 2010 Masters is scheduled for April 5-11” -> this request takes 300ms
  • The XHR message response handler takes this XML Element and puts it into a DIV tag
  • The total execution time of this operation takes 324ms

Unless there is a very good reason for using XHR in a use case like this I recommend to simply generating the initial HTML with the text that should be displayed. Even if the server has to do some additional processing here to e.g.: replace placeholders with the actual text I am sure this won’t take up 300ms.

Step 6: Optimizing JavaScript execution and load performance

The Masters web site is not that heavy on JavaScript but uses it in some spots. The first thing that I thought is interesting is the way they load libraries like jQuery. Instead of using the libraries as they are provided by John Resig they download the library in a string and eval the code as explained in the following blog by SproutCore: Faster Loading Through eval().  As pointed out in the Caveats section of their blog – loading the text is faster as you avoid that the JavaScript is parsed and executed when it gets loaded. However – execution in general can be up to 4 times slower when you actually call the eval method. This technique is great to delay load JavaScript code, but in this case here it is executed right away consuming more time than necessary. The following screenshot shows the execution of the jQuery library when it gets eval’d:

Faster Loading of JavaScript is not necessarily faster when done through eval
Faster Loading of JavaScript is not necessarily faster when done through eval

The general approach of speeding up loading JavaScript files with this technique is definitely interesting and works well in certain use-case scenarios but I believe it doesn’t make sense here.The last thing I want to analyze is the data grid on the last page in my example. The data is retrieved via an XHR call using XML as data format. Based on the current sorting setting, the data is sorted in JavaScript, a HTML table is created and set to the DIV tag that holds the space for the grid. Overall it takes about 800ms in pure JavaScript to perform these actions and about 790ms to retrieve the XML. The following screenshot shows parts of the sorting and rendering:

JavaScript trace showing data grid sorting and html manipulation
JavaScript trace showing data grid sorting and html manipulation

One suggestion here is to do the actually initial sorting already on the server and not in JavaScript. It is also interesting to see that changing the visibility of certain DOM elements takes up quite some time – depending on how much content there is within these elements. Analyzing these things is really helpful in identifying areas of potential performance improvements 🙂


With increasing number of online visitors during the main event, content delivery could become a serious performance problem as the servers will be bombarded with more requests than necessary. Following best practices like using a Content Deliver Network, leveraging the browsers cache, minifying content and optimizing AJAX/JavaScript execution will greatly improve web site performance and will lead to happier users. Happier users lead to more clicks and ultimately to more revenue through ads :-)I recommend looking at the following links to learn more: Google Web Performance Best Practices, Yahoo Best Practices to Speed up your Web Site, Steve Souders Blog, How to Speed Up sites like vancouver2010.com by more than 50% in 5 minutes, How to analyze and speed up content rich web sites like www.utah.travel in minutes and Webinar with Monster.com on Best Practices to prevent AJAX/JavaScript performance problems

Andreas Grabner has 20+ years of experience as a software developer, tester and architect and is an advocate for high-performing cloud scale applications. He is a regular contributor to the DevOps community, a frequent speaker at technology conferences and regularly publishes articles on blog.dynatrace.com. You can follow him on Twitter: @grabnerandi