Measuring site performance with JavaScript on mobile

There is a lot of talk around responsive Web design being too slow or too resource intensive and that other methodologies can achieve better performance. I don’t want to go into the details of which approach is better because I think different scenarios require different solutions. What is certainly true in all cases is that a Web site or app that loads faster is better than one that is slow. Companies like Google, Gomez and Akamai have all published papers and survey results showing how speed affects user perception of a service from your desktop computer and even more on a mobile device (KISSmetrics has also drawn a nice infographic for the lazy ones). This is the first article and another one will follow shortly.

The Navigation Timing API

Up until recently browsers have taken care of everything around resource prioritization, memory management and resource loading. With the rise of JavaScript, Web developers feel the need to be more in control and at the same time have more responsibility. If a Web app requires a lot of resources you might want to tweak what you load when based on the actual performance loading a page. The W3C has a number of specs in the works, some of which already implemented by browsers, that allow Web developers to measure how quickly Web contents are loaded. The Navigation Timing API is already implemented by IE (9 and later), Chrome and Firefox on the desktop (also see can I use) and on mobile by IE9 and later, Android 4.1 and Chrome on Android.
You are probably all familiar with WebKit inspector’s resources panel; look at this screenshot from an early implementation of the page resources, here you can see how long each resource took to load and you have details about when the request started, how long the browser waited and how long it took to transfer.

WebKit inspector’s resources panel, taken from https://www.webkit.org/blog/197/web-inspector-redesign/

The Navigation Timing API is a first step in this direction. In the past you would have used Date.now() to measure the interval of time between two events, but with the Navigation Timing API you get access to the full timing information related to the page, from when the browser opened the connection to when it resolved the DNS name to when it finished loading the page. All in milliseconds. I should clarify that the Navigation Timing API gives you information about the entire page, not each resource that composes it.

How to measure the page speed?

I found a lot of great articles about the Navigation Timing API and a couple of examples that really caught my eye, but I did not find an example that I could really copy and paste, so I thought I’d create one. Check it out at http://logme.mobi/jsnt/index.php

My example is quite simple, load a basic HTML page with some text and an image and record how long it takes to load. There are few things to note. First of all my code is VERY simple, I wanted it to be this simple, this way it’s a lot easier for you to read it and copy what you need. It’s all in one file, making it dead easy to see all the piece.

The Navigation Timing API introduces a new attribute, window.performance, which hosts 2 more attributes called timing and navigation. timing holds timing information about the loading of the page and navigation holds information about the actual HTTP request performed, i.e. if it navigated there (clicked on a link or the user entered the URL), if it’s a reload or a history traversal, going either back or forward. Simple.

Let’s start with the good news, all three major desktop browsers support the unprefixed attribute, window.performance. If you wanted to support older versions of Chrome or IE9 beta you must use respectively webkitPerformance and msPerformance (I did not find any references of mozPerformance on MDN, so I assume Mozilla went straight to the unprefixed version). On mobile the API is supported, unprefixed, on IE9 and higher, Android 4 and Chrome on Android. It is not supported on any version of iOS up to 6. Unless you have a very good reason for this, it is safe to stick to the standard, but just in case you wanted, I have written a simple check in my script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
featureDetect.supported = (window.msPerformance 
   || window.webkitPerformance || window.performance
   ) ? true : false;
 
[...]
 
featureDetect.unprefixed = (self.performance) ? true : false;
 
[...]
 
if (featureDetect.unprefixed) {
  var t = window.performance.timing;
} else if (featureDetect.prefixed == "ms") {
  var t = window.msPerformance.timing;
} else if (featureDetect.prefixed == "webkit") {
  var t = window.webkitPerformance.timing;
} else {
  alert("Unexpected error while fetching navigation timing data.");
}

The main action happens in printIt(), there I look at the window.performance.timing array and loop through each value to calculate the time each step took. I use the order array to order the different steps. Depending on what you are measuring you might want to look at different parts of the load process. For example you might have heard Steve Souders recommending that you avoid redirects, but then we all see how Twitter, Facebook and Google send us through one if not more redirects to follow a link. How much do those cost? If there was in fact a redirect the timing attribute will contain the redirectStart and redirectEnd values. The URL I provided earlier is a tiny PHP script that redirects the browser to a static page, for me, the redirect takes about 340ms, i.e. a third of the total load time, that’s 1/3 of the time wasted.

You now have an idea of the information that you can collect with the Navigation Timing API. Microsoft has a more complete example that also gives you a sense of how a page gets slower as you add resources, Navigation timing (although it is designed to be cross-browser, when I tried with Chrome 22 and 23 it did not run correctly, works fine with Firefox and IE).

Can I debug from my PC?

The short answer is “nearly”. You can enable the remote debugger on Chrome for Android or use Visual Studio for Windows Phone and dump data from the window.performance.timing array. For the standard Android browser, you still have to rely on something weinre.
If you wanted to collect information on a server for statistical purposes you could build your own format or you could use HAR; either way you will need a server to collect the information.

What else?

There are two other specs that are very much complementary to the Navigation API, the Performance Timeline and Resource timing. In short, the first one lets you see in which order each resource has been loaded by the browser and the second one lets you access detailed loading information of each resource. While the Navigation timing API gives you an overview of the whole page load, you might want to know how long each image or each external script took to load. These specs are already in very good shape, so far IE10 is the only one to implement them with Chrome coming soon. I will cover these in another article very soon.
If you have followed recent trends in Web design you will understand why these API’s will be very helpful. Think of responsive Web design where some resources are loaded selectively, it can be hard understanding exactly why your page is slow unless you can see exactly what happens and when. If you are relying on external resources (like Google analytics or a facebook button) you might want to avoid loading them if there is too much network latency. IE9 and later already implement a property called msFirstPaint that tells you when the document began to be displayed. Chrome already implements the memory property that gives access to JavaScript memory usage data and the Web performance WG is working on a spec.

Wait! Where’s the code?

I could have setup a repository for my example, but honestly, it’s so small that you can just go ahead, right-click and save it.

Read more

I did a lot of reading before I wrote this article, these are some of the useful resources that I collected:

This article is cross-posted on Nokia Developer’s site at Measuring site performance with JavaScript on mobile.

5 thoughts on “Measuring site performance with JavaScript on mobile

  1. Matt Smith

    Great review. The Navigation Timing API is terrific, I just wish it was more widely supported. Right now a lot of mobile browsers don’t support it, which is a shame because we’ve never been able to get data from the DOM this accurate before. http://caniuse.com/#search=navigation

    1. Andrea Post author

      There is commitment from the Chrome team, so it is coming. The only one that is not playing nice is Apple, right now.

      1. Andy Davies

        Apple voted for the standards adoption at the W3C so it should come to Safari sooner or later.

        Version 2 of the Nav Timing spec is on the works and that includes details on how long it too the phone’s radio to wake from sleep too.

  2. Philip Tellis

    We started measuring Real User Performance at Yahoo! back in 2005 and all those years of research ended up in an opensource library called boomerang that does performance measurement for browsers with and without the NavTiming API. It also measures bandwidth and latency, dns service time and more.

    While I no longer work at Yahoo!, I’m still the lead developer on the project. The code is available either at https://github.com/bluesmoon/boomerang (latest dev code) or https://github.com/lognormal/boomerang (latest stable code).

    It’s BSD licensed.

    Philip

Comments are closed.