Simplified Resource Timing and User Timing

In light of last week's discussion, Tony and I have come up with simplified
versions of the Resource Timing and User Timing APIs. Please take a look and
let us know what you think.

Thanks,
James

Resource TimingIDLinterface PerformanceResourceTiming {
 readonly attribute DOMString url;
 readonly attribute unsigned long long redirectStart;
 readonly attribute unsigned long long redirectEnd;
 readonly attribute unsigned long long fetchStart;
 readonly attribute unsigned long long domainLookupStart;
 readonly attribute unsigned long long domainLookupEnd;
 readonly attribute unsigned long long connectStart;
 readonly attribute unsigned long long connectEnd;
 readonly attribute unsigned long long secureConnectionStart;
 readonly attribute unsigned long long requestStart;
 readonly attribute unsigned long long responseStart;
 readonly attribute unsigned long long responseEnd;
 readonly attribute unsigned long long fetchEnd;
};

[Supplemental] interface PerformanceTiming {
 ResourceTiming[] getResourceTimings (in optional Location location);
 void enableResourceTimings();
 void disableResourceTimings();
 void clearResourceTimings();
};
DescriptiongetResourceTimings()Returns a snapshot of the currently collected
resource information in the event log. If a location is specified, only
entries with a matching location are returned. The log must have capacity
for at least 1000 resources. After that, the UA may choose to ignore new
resources.
enableResourceTimings()Enable resource timing collection. When enabled, the
event log will record the timings for any new resources that are loaded. By
default, resource timings are disabled.
disableResourceTimings()Disables resource timings. New entries are no longer
collected in the event log.
clearResourceTimings()Clears the event log of all resources.
ExamplesGet Everythingperformance.timing.getResourceTimings()
-> [{url: “http://resource1”, redirectStart: 1, … },
   {url: “http://resource2”, redirectStart: 2, … },
   {url: “http://resource2”, redirectStart: 3, … },
   …]
Get One Resourceperformance.timing.getResourceTimings(“http://resource1”)
-> [{url: “http://resource1”, redirectStart: 1, … }]
One Resource Requested Multiple Timesperformance.timing.getResourceTimings(“
http://resource2”)
-> [{url: “http://resource2”, redirectStart: 2, … },
   {url: “http://resource2”, redirectStart: 3, … }]
Get a Specific Resource
<script src=”http://resource1” id=”myElement”></script>
...
performance.timing.getResourceTimings(document.getElementById(‘myElement’).src)
-> [{url: “http://resource1”, redirectStart: 1, … }]

User TimingIDLinterface UserMark {
 readonly attribute DOMString name;
 readonly attribute unsigned long long value;
};

[Supplemental] interface PerformanceTiming {
 const string MARK_FULLY_LOADED = "fullyLoaded";
 const string MARK_FULLY_VISIBLE = "fullyVisible";
 const string MARK_ABOVE_THE_FOLD = "aboveTheFold";
 const string MARK_TIME_TO_USER_ACTION = "timeToUserAction";

 void mark(in DOMString markName);
 UserMark[] getMarks(in optional DOMString markName);
 void clearMarks();
};

Descriptionmark()Creates a new entry in the event log with the given name.
The value is the current time according to the monotonic clock. The event
log must be large enough to record at least 1000 marks. After 1000 marks,
the UA may choose to ignore subsequent calls to mark().
getMarks()Returns a snapshot of the currently known marks. If a mark name is
specified, only entries matching that mark name are returned.
clearMarks()Clear the event log of all marks.
ExamplesMultiple Marksperformance.timing.mark(“start”);
performance.timing.mark(“end”);
performance.timing.getMarks();
-> [{name: “start”, value: 1},
   {name: “end”, value: 2}]
performance.timing.getMarks(“start”);
-> [{name: “start, value: 1}]
Repeated Marksperformance.timing.mark(“step”);
performance.timing.mark(“step”);
performance.timing.getMarks(“step”);
-> [{name: “step”, value: 1},
   {name: “step”, value: 2}]
Rationale for significant changes

   1. Resource Timings no longer have a “type” and “id”.
   The id and type attributes make sense for many types of resources which
   have associated DOM elements. But a strong associations between DOM elements
   and the requests performed isn’t always the case. This leads to surprising
   behavior for both the data members and their associated getter methods:
      1. id doesn’t mean anything for a CSS or plugin subresource.
      2. id is a snapshot at the time the request was made. It may change
      during or after the request.
      3. id may not be unique and an element may initiate multiple requests.
      4. The initiator may be indeterminate and thus the id or type could be
      misleading.

The getter methods are largely redundant with document’s getElementById and
getElementsByTagName and are missing the functionality of
getElementsByClassName and getElementsByName. Encouraging users to use
existing DOM querying methods to find URLs to look up in the map enables the
same usage patterns, but is ultimately more flexible/future-proof and keeps
the interface simpler.

   1. Resource Timing is now explicitly enabled.
   Browsers take great care to use memory efficiently. While it was measured
   that the interface will consume 10s of K for typical
sites<http://lists.w3.org/Archives/Public/public-web-perf/2010Dec/0024.html>,
   all calculations were based on 200 resources or less. In reality, long
   running apps (and even traditional pages that rotate ads or periodically
   beacon) will eventually max out the structure (currently 1,000 entry limit).
   1,000 x 124 bytes is now 124k... and that’s just one tab.

   This still may not seem like a terrible amount of memory, but couple that
   with the fact that very few pages will actually be using this data. Even
   sites that do use the interface will probably only do so to sample
   performance on a small subset of requests (due to the large upload size of
   the JSON -- ~350bytes/entry without URLs).

   Popular browser developer tools require the user to explicitly enable
   recording of network resources, following that precedent we are requiring
   timing of resources to be explicitly enabled.

   As an aside, the explicit start/stop also removes the need for the
   complexity of buffer size management (onbufferfull and
   setResourceTimingBufferSize()).
   2. User Timing no longer has measures.
   The value of User Timing is to provide a monotonically increasing, high
   precision timer which would otherwise be unavailable; as well as to provide
   a standard location for developer tools and extensions to find application
   specific timings. Measures are syntactical sugar that a JS library could
   trivially layer on if developer wants to think about times in terms of
   measures. Measures were omitted from the Navigation Timing and Resource
   Timing APIs because they do not provide additional data and complicate the
   interface. To be consistent, they have been omitted from User Timing as
   well.



It is worth noting that any of these features could be added back in should
there be sufficient demand. Simplifying the API will allow us to standardize
on the core faster and expand if necessary.

Received on Wednesday, 27 April 2011 18:31:58 UTC