RE: Resource Timing - What's included

Great feedback Kyle.

I should've been clearer as well about what I meant regarding "resources pulled from cache".  Here are two different types of browser caches and how they would affect the Resource Timing (RT) arrays:
1) Resources that are already in the browser's disk cache, for example, from loading the page yesterday: *would* be included in the RT arrays.  Examples id="4" and id="5" below show this.

2) Resources that are referred to multiple times in the same page ("1a", "1b", "1c"):  Our current thoughts are that these resources *should not* be included, as my understanding is that all current browsers optimize this case and do not initiate network requests for duplicate resource URIs (eg, for "1b" and "1c", the browser wouldn't get 1.jpg again).  Additionally, these types of resources are not shown in browsers' Net panels, or from a network sniffer.

I could see including them for other reasons -- completeness of listing all of the resources, whether or not they were retrieved from the network.  But to me, it seems like listing every resource on the page would include a lot of redundant data, many of them without network latencies.

Your point about resources affecting the timing of the page load is valid.  But in this case, the only "interesting" attributes that those types of resources would have in the RT arrays would be fetchStart/loadStart/loadEnd timing, all of which can be captured today using JavaScript.

I would agree with you that the HTTP status code of the resource should not exclude it from the RT array.  404/500/etc should all be included.  If the browser "initiates" a request, whether or not it was completed, we should include it in the array.

- Nic

-----Original Message-----
From: Kyle Simpson [mailto:getify@gmail.com] 
Sent: Wednesday, March 23, 2011 8:58 AM
To: Nic Jansma; public-web-perf@w3.org
Subject: Re: Resource Timing - What's included

I'm a little concerned about this spec not including "resources pulled from cache" in the reporting. Well, let me be even clearer: "duplicate requests for the same resource, subsequent ones of which come from cache".

This operation, while not nearly as "costly" as if it's loaded over the network, does in fact still affect the timing of things on the page. For instance, a <script> tag will block, even for the few dozen ms of pulling from cache, other rendering, and in some cases, resource loading.

To have the most accurate picture of timing (and what caused certain delays), I think all resource loading should be included, and just marked with a type that indicates if it came from browser cache, or was a duplicate-from-cache request, or from the network, etc.

Moreover, resources that result in something other than 200/301 still affect the performance/timing of the page, so should they (with the respective response code) also be included, again for completeness sake? A request for a script that results in a 404 or 500 still has a timing cost associated with it.

--Kyle







From: Nic Jansma
Sent: Tuesday, March 22, 2011 6:55 PM
To: public-web-perf@w3.org
Subject: Resource Timing - What's included


We have recently been discussing what resources should be included in the Resource Timing arrays.  This email is intended to explain our current thoughts and solicit feedback and concerns.

Here's a summary of the thoughts and constraints we face when considering what resources to include in Resource Timing:
*         Take inspiration from, and expose the same information to the web 
developer as in the Net panels in Firebug/Chrome/IE
*         Provide a complete list of resources that were download, including 
same-origin and cross-origin
*         Respect the privacy of the user by not explicitly exposing 
additional information about what sites they've previously visited (via timing attacks targeting content that might be in their cache)
*         Protect the security of cross-origin servers and their resources

Below is a small example enumerating the resources that would be included in Resource Timing, starting from a sample HTML page.  Our proposal is to capture all of the "download-able" resources (from the browser's perspective), as opposed to the actual "download-ed" resources.  If we only exposed the download-ed resources, and not items that are already in the cache, the absence of the resource in Resource Timing gives definitive knowledge that the resource is already in the user's cache, which wouldn't be respecting their privacy (especially for content on other domains).

Note: This email also exposes some of our thoughts regarding what to do about resources from non-same-origin domains, but does not go into details. 
Jatinder will follow up with our thoughts on how we can address resources loaded from non-same-origin domains.

Here's a sample HTML page to explain our thoughts.  I've highlighted the resources that would be included in Resource Timing, and go into details
below:

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <img src="1.jpg" id="1a" />
        <img src="1.jpg" id="1b" />
        <img src="1.jpg" id="1c" />
        <img src="2.jpg" id="2" />
        <img src="http://otherdomain.com/3.jpg" id="3" />
        <img src="4.jpg" id="4" /> <!-- already in cache -->
        <img src="http://otherdomain.com/5.jpg" id="5" /> <!-- already in cache -->
        <img src="6.jpg" id="6" /> <!-- redirects to 6b.jpg -->
        <script>
            xmlHttp = new XMLHttpRequest();
            xmlHttp.open("GET", "xhr-get-cacheable.xml");
            xmlHttp.send(null); // resource is cacheable

            xmlHttp = new XMLHttpRequest();
            xmlHttp.open("GET", "xhr-get-cacheable.xml");
            xmlHttp.send(null);

            xmlHttp = new XMLHttpRequest();
            xmlHttp.open("GET", "xhr-get-no-cache.xml");
            xmlHttp.send(null); // resource is not cacheable

            xmlHttp = new XMLHttpRequest();
            xmlHttp.open("GET", "xhr-get-no-cache.xml");
            xmlHttp.send(null);

            var rt = performance.getResourceTimings();
        </script>
    </body>
</html>

With these assumptions:
*         The page is loading from mydomain.com.  Two resources (id="3" and 
id="5") are loading from otherdomain.com
*         The browser cache is empty except for 4.jpg on mydomain.com, and 
5.jpg on otherdomain.com.  Neither of these cached resources require network revalidation.
*         All responses are HTTP 200, except 6.jpg which 301 redirects to 
6b.jpg

Notes about each specific resource from the sample HTML page:
*         id="1a": Included, because this is the browser's first request for 
1.jpg.  All timestamps filled out as normal.  We associate id="1a" because it was the first initiator of the request for 1.jpg.
*         id="1b": Not included, because the browser already initiated a 
download via id="1a" and won't initiate a second download.
*         id="1c": Not included, because the browser already initiated a 
download via id="1a" and won't initiate a second download.
*         id="2": Included, because this was the browser's first request for 
2.jpg.  All timestamps filled out as normal.  This re-uses an existing connection so its domainLookup and connectStart times are the same as fetchStart (as an example).
*         id="3": Included, because this was the browser's first request for 
3.jpg.  On a second domain, so the only timestamps available are fetchStart, loadEventStart and loadEventEnd.  All others are zero'd.
*         id="4": Included, because this was the browser's first request for 
4.jpg.  Was in the cache, so its times from fetchStart through loadEventStart are all 41 (no elapsed time).  This exposes the same precision as attaching a load handler to the img and timing the elapsed time.
*         id="5": Included, because this was the browser's first request for 
5.jpg.  On a second domain, so the only timestamps available are fetchStart, loadEventStart and loadEventEnd.  All others are zero'd.  Was in the cache, so the time between fetchStart and loadEventStart are very close but exposes the same precision as attaching a load handler.
*         id="6": Included, because this was the browser's first request for 
6.jpg.  All timestamps filled out as normal.  Was redirected to 6b.jpg, but its "url" attribute is the original URL as the developer specified.
*         1st xhr-get-cacheable.xml (XHR is cacheable): Included
*         2nd xhr-get-cacheable.xml (XHR is cacheable): Not included as the 
browser re-uses the resource
*         1st and 2nd xhr-get-no-cache.xml (XHR is set to Cache-Control: 
no-cache): Both are included as the browser gets the resource twice.

This is an example of getResourceTiming() after this page load.  UTC timestamps are simplified on a timeline from 0 to 110.  For reference, resourceType 4 = RESOURCE_IMAGE and 8 = RESOURCE_XMLHTTPREQUEST:

[{
    "url":"http://mydomain.com/1.jpg",
    "resourceType": 4,
    "id": "1a",
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 10,
    "domainLookupStart": 10,
    "domainLookupEnd": 11,
    "connectStart": 12,
    "connectEnd": 13,
    "requestStart": 13,
    "requestEnd": 14,
    "responseStart": 14,
    "responseEnd": 15,
    "loadEventStart": 16,
    "loadEventEnd": 17
},{
    "url":"http://mydomain.com/2.jpg",
    "resourceType": 4,
    "id": "2"
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 20,
    "domainLookupStart": 21,
    "domainLookupEnd": 21,
    "connectStart": 21,
    "connectEnd": 21,
    "requestStart": 23,
    "requestEnd": 24,
    "responseStart": 24,
    "responseEnd": 25,
    "loadEventStart": 26,
    "loadEventEnd": 27
},{
    "url":"http://otherdomain.com/3.jpg",
    "resourceType": 4,
    "id": "3"
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 31,
    "domainLookupStart": 0,
    "domainLookupEnd": 0,
    "connectStart": 0,
    "connectEnd": 0,
    "requestStart": 0,
    "requestEnd": 0,
    "responseStart": 0,
    "responseEnd": 0,
    "loadEventStart": 36,
    "loadEventEnd": 37
},{
    "url":"http://mydomain.com/4.jpg",
    "resourceType": 4,
    "id": "4"
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 41,
    "domainLookupStart": 41,
    "domainLookupEnd": 41,
    "connectStart": 41,
    "connectEnd": 41,
    "requestStart": 41,
    "requestEnd": 41,
    "responseStart": 41,
    "responseEnd": 41,
    "loadEventStart": 42,
    "loadEventEnd": 42
},{
    "url":"http://otherdomain.com/5.jpg",
    "resourceType": 4,
    "id": "5"
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 51,
    "domainLookupStart": 0,
    "domainLookupEnd": 0,
    "connectStart": 0,
    "connectEnd": 0,
    "requestStart": 0,
    "requestEnd": 0,
    "responseStart": 0,
    "responseEnd": 0,
    "loadEventStart": 52,
    "loadEventEnd": 52
},{
    "url":"http://mydomain.com/6.jpg",
    "resourceType": 4,
    "id": "6",
    "redirectStart": 61,
    "redirectEnd": 70,
    "fetchStart": 70,
    "domainLookupStart": 71,
    "domainLookupEnd": 71,
    "connectStart": 72,
    "connectEnd": 73,
    "requestStart": 73,
    "requestEnd": 74,
    "responseStart": 74,
    "responseEnd": 75,
    "loadEventStart": 76,
    "loadEventEnd": 77
},{
    "url":"http://mydomain.com/xhr-get-cacheable.xml",
    "resourceType": 8,
    "id": ""
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 81,
    "domainLookupStart": 81,
    "domainLookupEnd": 81,
    "connectStart": 82,
    "connectEnd": 83,
    "requestStart": 83,
    "requestEnd": 84,
    "responseStart": 84,
    "responseEnd": 85,
    "loadEventStart": 86,
    "loadEventEnd": 87
},{
    "url":"http://mydomain.com/xhr-get-no-cache.xml",
    "resourceType": 8,
    "id": ""
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 91,
    "domainLookupStart": 91,
    "domainLookupEnd": 91,
    "connectStart": 92,
    "connectEnd": 93,
    "requestStart": 93,
    "requestEnd": 94,
    "responseStart": 94,
    "responseEnd": 95,
    "loadEventStart": 96,
    "loadEventEnd": 97
},{
    "url":"http://mydomain.com/xhr-get-no-cache.xml",
    "resourceType": 8,
    "id": ""
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 100,
    "domainLookupStart": 101,
    "domainLookupEnd": 101,
    "connectStart": 102,
    "connectEnd": 103,
    "requestStart": 103,
    "requestEnd": 104,
    "responseStart": 104,
    "responseEnd": 105,
    "loadEventStart": 106,
    "loadEventEnd": 107
}]

- Nic 

Received on Wednesday, 23 March 2011 16:51:59 UTC