Real User Measurements (RUM): why is this web app running slowly, Part 9

This is a continuation of a series of blog entries on this topic. The series starts here.

Real User Measurements (RUM)

The other way to obtain client-side Page Load time measurements – and one that is becoming increasingly popular – is a tool that measures page load time from inside the browser. The web browser-based performance tools we have looked at like ChromeSpeed or the corresponding Network tab in the Internet Explorer Developer Tools measure page load time from inside the web client. But, as we saw, those performance tools function like YSlow, requiring you to have direct (or remote) access to the web client. Real User Measurements refer to measurements of how long it took to access your web site acquired from inside the web browser running on your customers’ machines and operated directly by them. Those are the real users whose experience with our web sites we want to capture and understand.

There are two important aspects of gathering client-side Page Load time measurements: (1) obtaining the measurements, of course, and, crucially, (2) figuring out a way to send the measurements from the machine where the browser is running back to the data gatherer. Conceptually, a piece of JavaScript code that subscribes to both the DOM’s initial window.unload event and the window.load event can gather the necessary timings. (In practice, this is a bit more complicated because you actually need two pieces of JavaScript code to execute, one to get the time the window.unload event fired in the previous browser window, one to get the load time for the current window, and a mechanism to pass the time of the unload forward to the next window to calculate an interval delta.) Once it is acquired, the timing data can then be transported from the browser using a web beacon sent to a designated location. An example of a JavaScript-based tool that does precisely this is Google SiteSpeed, which is part of its Google Analytics suite of tools. Googel SiteSpeed gathers web application timing data and then sends the Page Load Time measurements back to a Google Analytics data center for collation and analysis.

Real User Measurements of web application response time, gathered using JavaScript and forwarded to some Host web site for analysis, contrast with an earlier technique entailing a monitoring service that is paid to generate synthetic Requests to your web site and measure their web response times. That first generation of commercially available web performance tools measured end-to-end response times for web requests by generating requests to your web application from inside their application, using a script to supply access parameters like a user name and password, for example. Periodically, these monitoring services poll your web site, generating and then transmitting synthetic GET Requests. By simulating actual customers exercising your web apps, the service is able to monitor the availability of the web site and measure its responsiveness. These monitoring services remain in use among companies doing business on the web, available from suppliers like Keynote and others.

Currently, measurements based on the timing of synthetic web requests are beginning to be superseded by Real User Measurements, or RUM for short, which access timing information directly from inside the web browser. Now that there is a standard interface, known as the Navigation/Timing API, adopted in 2012, it is markedly easier to gather web client response time data directly from your web site’s customers.

This timing data, the Real User Measurements, are accessible using a JavaScript code snippet that can be embedded in the page’s HTML. To illustrate this approach, the snippet of JavaScript code in Listing 1 adds a handler function named CalculateLoadTime to run when the DOM’s window.load event fires. It then uses the built-in window.performance object to retrieve a high resolution clock value representing the current time and a timer value set when the original GET Request was issued. The difference between the two timer values is the page load time measurement. The built-in performance object that the script accesses automatically provides the timing data that the script uses to calculate Page Load time. I will explore the properties of the performance object and explore its uses in more detail in a moment.

<script type=”text/javascript”>
// add load event listener.
window.addeventlistener(“load”, Calculateloadtime, false);
function Calculateloadtime() {
// get current time.
var now =;
// calculate page load time.
var page_load_time = now – performance.timing.navigationstart;
// write the load time to the f12 console.
if (window.console) console.log(page_load_time);
<!- main page body is here. –> </body>

Listing 1. Accessing the DOM’s performance object in a Load event handler.

Developers with some experience using JavaScript to manipulate the DOM will recognize that you would not want to incorporate this code snippet as is directly into your web page because the window.onload event handler is probably already overwritten in order to execute a piece of initialization script code after the browser has resolved all of the page’s external references. In that event, to gather the timing data, you could simply copy the CalculateLoadTime() function body and paste into an existing window.onload event handler. To get the most accurate measurement possible, you would want the timing code to execute at the end of the window.onload event handler routine, of course. As discussed in earlier posts, it is not unusual for the window.onload event handler to perform a significant amount of DOM manipulation.

Once the internal web client timing data is gathered, it can then be transmitted to an external web site using a web beacon, which is a GET Request for a trivial HTTP object (often a Request for a one-pixel transparent .gif) issued from JavaScript code where the subsequent Response message is designed to be thrown away. The web beacon Request message contains the payload. The GET Request is fashioned so that it appends a set of parameters to the Request message that contain data of interest. Web beacons are widely used by web analytics programs like Google’s or New Relic’s to get data on web browser activity from the web client back to their data centers for processing and analysis. The data in the beacon payload is typically about usage of the current web page.

Among the popular tools that use this measurement technique is Google Analytics, a tool that Google supplies free of charge to smaller sites that captures and reports on many kinds of web page usage statistics, including the SiteSpeed timing data that measures Page Load time. Google Analytics introduced the SiteSpeed measurements in 2010. The SiteSpeed data is sampled by default, by the way. Unless you change the Google Analytics defaults (see documentation on the _setSiteSpeedSampleRate() for details), SiteSpeed data is sampled at a 1% rate. There is even a free Google Analytics plug-in for WordPress-based web sites that makes it very easy for small and medium-sized businesses with limited technical resources to start utilizing the company’s web analytics reporting suite.

To help make gathering the SiteSpeed measurement data more reliable, Google put its weight behind a proposal to the W3C, the standards body responsible for all web technology and protocols, to add a standard Navigation Timing object to the DOM and then implemented that API in Chrome. Shortly after the Navigation Timing API was submitted to the W3C by Google, Microsoft, Yahoo and others, it was adopted by all the major web clients, including Chrome, Internet Explorer, Firefox, Safari and Opera. (For details on support of the API in different browsers, see

In the next post, I will take a closer look at the Navigation Timing API.


Tagged , . Bookmark the permalink.

One Response to Real User Measurements (RUM): why is this web app running slowly, Part 9

  1. Pingback: HTTP/2 : Winds Of Change – Part I | Practical Performance Analyst

Leave a Reply

Your email address will not be published. Required fields are marked *