RE: Unified Timing Proposal

Thank you Tony and James.  Your proposal has given us a lot of food for thought.  The fact that we're discussing a simpler interface such as this is a good reason to step back and consider the direction we're taking the UserTiming (UT) and ResourceTiming (RT) specs.  Maybe they're getting too complex?

We discussed a couple topics of feedback on the conference call -- here is a digested version of what we talked about and our initial feedback.

One of our main concerns with the Unified Timing Proposal is that it will reduce some of the functionality we have been building into the RT and UT specs, such as:

*         ResourceTiming: Initiator type

*         ResourceTiming: Initiator element IDs

*         ResourceTiming: The onBufferFull callback

*         UserTiming: Having separate concepts of marks and measures (allowing measures to specify arbitrary start and end marks, clearing them independently, etc)

*         The ability to easily separate UserTiming nodes from ResourceTiming nodes (I could see this being a larger problem as we add additional types to the Unified interface)
As you mention, one of the goals of the Unified Timing proposal is to allow easy expansion for future timing-related interfaces.  We agree that it would be great to design with future expansion in mind, but at the same time, we are worried about the constraints it may place on future interfaces.
As an example, let's pretend for a moment that NavigationTiming hasn't been designed yet, and the Unified Timing interface exists for UT and RT.  The question is: Would we be able to fit NavigationTiming into the Unified Timing interface?  We could add a new type (such as "Document") with all of the performance.navigation.timing attributes as marks.  The problem comes with the other metadata we provide for NavigationTiming -- such as performance.navigation.type and redirectCount.  I consider them essential attributes of the navigation, but don't see a way of incorporating them into the interface.  We could stick them in as "marks", but that would confuse timestamps with navigation metadata.  Would future interfaces be constrained by similar issues?
One thought we have is that if we build the right underlying support into the existing UT and RT interfaces, JavaScript library authors could easily release a library looking similar to the Unified Timing proposal that would simplify the view of the three interfaces.
Finally, if we go down this route, we will still have to have separate User Timing and Resource Timing specs (to get the specifics of their interactions correct), as well as a new Unified Timing proposal/spec.  UT and RT would then be dependent on the Unified Timing proposal being finalized, which will cause some delay in moving these all forward.

- Nic

From: public-web-perf-request@w3.org [mailto:public-web-perf-request@w3.org] On Behalf Of James Simonsen
Sent: Monday, April 11, 2011 9:30 PM
To: public-web-perf
Subject: Re: Unified Timing Proposal

On Fri, Mar 11, 2011 at 2:09 PM, James Simonsen <simonjam@chromium.org<mailto:simonjam@chromium.org>> wrote:
One of the things that's bothered me about the various timing specs is that each has its own separate interface, despite each basically doing the same thing. I've come up with a proposal for unifying Navigation Timing, Resource Timing, and User Timing under a single interface. Take a look and let me know what you think.

Tony and I spent some time cleaning up the Unified Timing proposal. We've come up with an API that uses the same concepts, but is much cleaner. I think this will make it a lot more appealing. Please take a look at it and let us know what you think.

Thanks,
Tony and James

API

[Supplemental] interface Performance {
 readonly attribute PerformanceLog log;
};

interface PerformanceLog {
 const unsigned short LOG_ALL = 0;
 const unsigned short LOG_RESOURCE = 1;
 const unsigned short LOG_APP = 2;

 void record(in unsigned short type,
             in optional unsigned short maxLength);
 void stop(in unsigned short type);

 const DOMString MARK_FULLY_LOADED = "fullyLoaded";
 void mark(in DOMString objectKey,
           in optional DOMString timingKey);

 void clear(in optional unsigned short type);

 Object getTimings(in optional DOMString objectKey);
 Object getDurations(in optional DOMString objectKey);
};

record

Starts or resumes recording of the given log type.


LOG_RESOURCE: An entry will be added to the log for every downloadable resource requested after this method is called. The objectKey will be the URL of the resource. A timingKey will always be added for fetchStart and fetchEnd. If the domain of the resource is the same as the domain of the root document, an additional timingKey will be added for: redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd.


LOG_APP: The mark() method behaves as described below.


LOG_ALL: Represents the union of LOG_RESOURCE and LOG_APP.


The number of entries returned by getTimings() and getDurations() is limited to maxLength. If maxLength isn't specified, the default is 1,000 entries.


By default, the log starts in LOG_APP mode.

stop

Stops recording of the given log type.


LOG_RESOURCE: An entry for each downloadable resources requested after this method is called will no longer be added to the log.


LOG_APP: The mark() method becomes a no-op.


LOG_ALL: Represents the union of LOG_RESOURCE and LOG_APP.

mark

Adds an entry of type LOG_APP to the log. The objectKey is the name of the key of the entry. This method may be called multiple times with the same key.


If a timingKey is not given, it will default to "value". The timestamp associated with this key will be the current time accurate to within 1ms.

clear

Removes all entries of type from the log.

getTimings

Returns an Object in JavaScript Object Notation (JSON) form consisting of all entries in the log. If an objectKey is given, only the matching entry is returned. The returned object adheres to the following JSON specificationn.


{

 "objectKey1": [{

   "timingKey1": Integer,

   "timingKey2": Integer,

   ...

 }],

 "objectKey2": [{

   "timingKey1": Integer,

   "timingKey2": Integer,

   ...

 }],

 ...

}

getDurations

Returns an Object in JavaScript Object Notation (JSON) form consisting of the value of the minimum timingKey subtracted from the maximum timingKey for each entry in the log. If an objectKey is given, only the matching entry is returned. The returned object adheres to the following JSON specification.


{

 "objectKey1": Integer,

 "objectKey2": Integer,

 ...

}

Examples

Resource timing

<script>
 performance.log.record(performance.log.LOG_RESOURCE);
</script>
<img src="http://example.com/foo.gif">
<script src="http://example.com/foo.js"></script>

> performance.log.getTimings()
{
 "http://example.com/foo.gif": [{fetchStart: 100, fetchEnd: 200}],
 "http://example.com/foo.js": [{fetchStart: 101, fetchEnd: 201}]
}
> performance.log.getTimings("http://example.com/foo.gif")
[{fetchStart: 100, fetchEnd: 200}]
> performance.log.getDurations()
{
 "http://example.com/foo.gif": [100],
 "http://example.com/foo.js": [100]
}
> performance.log.getDurations("http://example.com/foo.gif")
[100]

User timing (measure style)

<script>
 performance.log.mark("readEmail", "start");
 readEmail();
 performance.log.mark("readEmail", "stop");
</script>

> performance.log.getTimings()
{"readEmail": [{start: 123, end: 456}]}
> performance.log.getDurations()
{"readEmail": [333]}
> performance.log.getDurations("readEmail")
[333]

User timing (mark style)

<script>
 document.onclick = function() {
   performance.log.mark("clickTime")
 }
</script>

> performance.log.getTimings()
{"clickTime": [{value: 123}, {value: 234}]}
> performance.log.getTimings("clickTime")
[{value: 123}, {value: 234}]
> performance.log.getDurations()
{"clickTime": [0, 0]}

Received on Thursday, 14 April 2011 22:11:15 UTC