As web sites become more like applications, measuring and tuning their performance dramatically increases in importance, especially on mobile devices where latency and other performance-related factors have a high impact on user satisfaction. In fact, GigaOM just recently released findings that almost half of users are much less likely to return to a Web site that loads slowly on their handset.
We consider helping developers to measure real-world performance of their mobile sites to be so important that we were on the leading edge of implementing the W3C Navigation Timing interface in Internet Explorer 9, and helped drive it to Candidate Recommendation status very quickly. This interface is available via the window.performance
object on IE9 for Windows Phone “Mango” devices, and you can read more about the work we’ve done on this standard here and here. If you don’t have a Mango device, you can download the easy-to-use emulator from the App Hub on MSDN.
What Navigation Timing Measures
The Navigation Timing interface gives Web developers a way of measuring a complete end-to-end picture of user latency – that is, the total amount of time involved in various parts of the process by which a user first requests a Web resource until the time point where it has finished loading in the browser.
This is an important distinction from purely JavaScript-based measures that may be able to (roughly) measure, say, the time it takes to load a page, but cannot get access to more detailed information such as redirect timing or domain lookup latency.
Using the Navigation Timing features, you can measure things such as (but not limited to):
- Time needed to unload previous page
- Time elapsed to look up a page’s domain
- The time points at which the page DOM starts to load and then becomes interactive
- Time required to perform the window.onload event
- Total time required to load a page from initial navigation request
Using the Navigation Timing API
The Navigation Timing features are available from the window.performance object (as with any feature, your code should make sure that the given feature actually exists before attempting to use it), which itself just provides objects for timing and navigation. Assuming the feature is supported, you can use the window.performance.timing and window.performance.navigation objects to obtain timing data.
Navigation Information
The PerformanceNavigation Interface defines two properties and a few constants:
Property |
Description |
type |
The type of navigation. Can be TYPE_NAVIGATE (0), TYPE_RELOAD (1), TYPE_BACK_FORWARD (2), or TYPE_UNDEFINED (255). |
redirectCount |
Indicates the number of redirects the navigation experienced for the page to load in the browser |
The type field indicates what kind of navigation was measured. This can be either a normal navigation, a reload event, or a programmatic navigation event via the history object. NOTE: Navigations that result from client-side redirects such as using a <meta> tag with a refresh directive are not counted as redirects – the API reports these as whether they caused a reload or a navigation to a new URL.
Timing Information
The actual timing information for the navigation is available on the timing object, which implements the PerformanceTiming interface. Each of these properties represents a time point during the lifecycle of the navigation event. These time points, listed in order of their occurrence, are:
Timing Field |
Description |
navigationStart |
Time point at which the navigation begins |
unloadEventStart |
Time at which the user agent starts unloading the previous document, if there is one, otherwise 0 |
unloadEventEnd |
Time at which the previous document finishes unloading the previous document, otherwise 0 |
redirectStart |
If any redirects are involved, this is the time point at which the first fetch request that initiates the redirect starts, other wise 0 |
redirectEnd |
If there were any redirects involved, the time point at which the last byte of the last redirect is received, otherwise 0 |
fetchStart |
For HTTP GET requests, the time at which the user agent starts to check the application cache, otherwise the point at which the resource fetch starts |
domainLookupStart |
Time point at which the user agent starts the domain name lookup for the document. If the document is retrieved from the cache, this is the same as fetchStart |
domainLookupEnd |
Time at which the user agent finishes looking up the domain name. If the document is being retrieved from a cache or locally, same as fetchStart |
connectStart |
Time when the user agent starts establishing a connection to the server. If the document is retrieved from the application cache or otherwise locally, this is the same as domainLookupEnd |
connectEnd |
Time when the user agent finishes establishing a connection to the server. If the document is retrieved from the application cache or otherwise locally, this is the same as domainLookupEnd |
secureConnectionStart |
Optional attribute – it is undefined for user agents that don’t provide it. If HTTPS is used, this is the time point when the user agent starts the handshake process to secure the connection. If HTTPS is not used, this is 0 |
requestStart |
The time when the user agent starts requesting the document from the server, or from the application cache or other local resource |
responseStart |
Time point immediately following when the user agent receives the first byte of the response from the server, application cache, or local resource |
responseEnd |
Time point immediately following when the user agent receives the last byte of the response from the server, application cache, or local resource |
domLoading |
Time point when the user agent sets the readyState of the current document to “loading” |
domInteractive |
Time point when the user agent sets the readyState of the current document to “interactive” – this is the first point where the user can interact with the page |
domContentLoadedStart |
Time point right before the user agent fires the DOMContentLoaded event |
domContentLoadedEnd |
Time point right after the DOMContentLoaded event completes |
domComplete |
Time point right before the user agent sets the readyState to “complete” |
loadEventStart |
Time point right before the user agent fires the onload event |
loadEventEnd |
Time point right after the onload event completes |
To calculate the amount of time required for a particular navigation sequence, you can simply subtract one value from another. For example, to calculate the total time required to load a page, you can simply subtract navigationStart from loadEventEnd:
var perfData = window.performance.timing;
var pageLoadTime = perfData.loadEventEnd – perfData.navigationStart;
Or, if you wanted to see how long the request-response process took, you could simply use:
var connectTime = perfData.responseEnd – perfData.requestStart;
The Timing Sequence of Events
Each of the timing events fires at a defined point in the page navigation process, illustrated by the following figure:
Practical Usage
Having this data available inside your page can provide several real-world benefits. Site developers, for example, can implement a URL parameter switch that turns on performance testing for the page, allowing testers to gather data from live production pages. Or, a site might choose to implement an “opt-in” feature for live users to provide this performance feedback via XHR so that the site can measure how well pages are being navigated to in the wild.
Microsoft is committed to working with the W3C to create an interoperable way of measuring the performance of Web sites, of which the Navigation Timing API is just a start. Let us know how you’re using the API and what kinds of insights it has helped you find!
Happy Coding!
Joe Marini (@joemarini)
Principal Program Manager, Internet Explorer Windows Phone