W3C home > Mailing lists > Public > public-web-perf@w3.org > January 2015

Re: Notification for new navigation timing entries

From: Ilya Grigorik <igrigorik@google.com>
Date: Mon, 5 Jan 2015 16:35:05 -0800
Message-ID: <CADXXVKpdTk_Xssi1cMfTu8w+rikV4uCbvk4hDnH7WFKkPRrp8A@mail.gmail.com>
To: erik.arvidsson@gmail.com, public-web-perf <public-web-perf@w3.org>
Cc: Olli Pettay <olli@pettay.fi>, Eli Perelman <eperelman@mozilla.com>, Joshua Peek <josh@joshpeek.com>, Nat Duca <nduca@google.com>

"Today, ECMAScript code wishing to observe changes to objects typically
either creates objects wrapping the real data or employs dirty-checking
strategies for discovering changes. The first approach requires objects
being observed to buy into the strategy, making the user model more complex
and eroding composability of concerns. The second approach has poor
algorithmic behavior, requiring work proportional to the number of objects
observed to discover if any change has taken place. Both require increased
working sets." [1]

The above statement is a good description of the very problem we're trying
to solve for the performance timeline. Right now we have to rely on dirty
checking (plus have race conditions between multiple observers), and so far
we've been talking about creating an alternative ~observer API.. which is a
step forward, but doesn't address the composability concern. With that in
mind, it seems like Object.observe has already solved this, plus more:

- synthetic change records via notifier
- event filters via acceptList
- higher-level change records (aggregation, etc)
- observing multiple objects with a single callback
- ability to aggregate large changesets and focus on performance
- existing polyfills, and so on.

I'm covering the highlights, for full details see:
- http://www.html5rocks.com/en/tutorials/es7/observe/
- https://github.com/arv/ecmascript-object-observe

Concretely, the API would ~look like the following:
def observer(events) {
events.forEach(function(event) {
  // process event: event.entry.name, event.entry.entryType, etc...

// to subscribe to all perf timeline events...
Object.observe(window.performance, observer, ["navigation", "resource",
"mark", "measure", "renderer"]);

// to unsubscribe
Object.unobserve(window.performance, observer);

It seems like the right solution here is to extend our Performance Timeline
[2] to be compatible with Object.observe, instead of trying to invent a new
API... I think we would need a few special provisions* (similar to how
Array.observe provides a more efficient+detailed implementation), but
otherwise window.performance would just be another observable object.

* special provisions: keep propagating changes if buffer is full, don't
send notifications on buffer clear, and so on.

*Erik*: your name is on the Object.observe spec, wondering if you can
provide any thoughts or recommendations? For context, see:
https://github.com/w3c/performance-timeline/issues/1 - apologies about the
length of the thread, I think we've been incrementally reinventing O.o() :-)

[1] https://github.com/arv/ecmascript-object-observe#problem
[2] http://w3c.github.io/performance-timeline/#sec-performance-timeline

On Tue, Dec 9, 2014 at 4:55 PM, Ilya Grigorik <igrigorik@google.com> wrote:

> On Mon, Dec 8, 2014 at 5:14 PM, Nat Duca <nduca@google.com> wrote:
>> Correct me if I'm wrong, ilya, but the reason I think we were looking at
>> specifying when events are inserted in the timeline was because there were
>> no callbacks when events were actually inserted. This made it hard for JS
>> to "await" a navigation event.
> Yep, exactly. We don't have a notification mechanism for new perf events,
> which means that applications need to poll the buffers (ugh), and run the
> risk of trampling on each other (e.g. someone clears the buffer, causing
> everyone else to miss events).
> In PerformanceObserver, you would make an observer for nav events, listen
>> to its callback and then disconnect when they arrived. In that model, its
>> up to the browser when to deliver those callbacks, which lets us defer
>> their delivery as long as we think is necessary to get good performance.
>> That's much better for performance.
> Nav events in particular are probably not the best example, but otherwise
> yes that's exactly the model - e.g. listen for one of "mark", "measure",
> "resource", or "render" perf events and run relevant processing.
>> Ilya: to your point, having observers always get notifications sounds
>> great. But, if so, I wonder if we can figure out how we can specify things
>> like frame-timing events to never add to the buffer in the first place.
>> Since they have nonzero overhead to collect, we'd be avoiding a footgun if
>> they're only obtainable via observers.
> I've entertained the same thought.. if we have observers, do we need the
> buffer at all? And I think the answer might still be yes: what if I want to
> get frame-timing events for the initialization sequence of the page, prior
> to my app registering an observer? E.g. get timing events for first
> frame(s)? Does that mean I must register my observer as very first thing on
> my page, and will that give me what I'm after?
> ig
Received on Tuesday, 6 January 2015 00:36:13 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:04:40 UTC