w3c / performance-timeline

Performance Timeline
https://w3c.github.io/performance-timeline/
Other
111 stars 27 forks source link

When are new entries delivered to observer? #13

Closed igrigorik closed 9 years ago

igrigorik commented 9 years ago

Some entries have attributes that may take a long time to "finalize". For example, it may take 10s+ to get the loadEventEnd timestamp for NavigationTiming. When does an entry with such attributes become visible to the observer? Once all the attributes values are known, or can the entry be delivered sooner? We should clarify this in the spec.

Thinking out loud.. it seems like they would have to be delivered once finalized. If they're not, then you run into interesting issues: observer gets notified and calls getEntries(), which returns a copy of the event with partial attributes. However, from that point forward the retrieved entry wouldn't be updated with new attribute values, and observer wouldn't fire notifications for same entry with new attributes either, so there is no way to observe updated values.

natduca commented 9 years ago

Agreed that they should be delivered only when complete.

Maybe the real bug here is that there are a few "events" that have sibling "early" events. E.g. there's resource load events which are post-facto (and thus can take a while). But maybe there are down the road fetch events too that show the earlier timings...

This all gets to us moving to a stronger PerformanceObserver model: when we say that new events only go into the observer and not to the global timeline, then it becomes easier for us to add events for use cases instead of fearing saturating the timeline like we used to.

nicjansma commented 9 years ago

I would like to see if there's a way we could allow consumers of ResourceTiming to get notified of new entries prior to their completion (eg before responseEnd is set).

Ideally, I would like to be notified of new RT entries as soon as startTime is known.

One use case is to allow pages to monitor for new outgoing network requests, which would also give you the ability to know how many networking requests are in-flight. You could theoretically build a "busy" indicator with this.

Specifically, what we want, is to be able to better monitor when all of the resources triggered by a SPA soft navigation have completed. The body 'onload' event is no longer relevant for SPA apps. Today we're doing this by monitoring for changes to the DOM via MutationObserver and hooking into onload/onerror events, which is not efficient. We also cannot monitor all types of resources in this way (eg fonts).

Alternatively, what if there was a new interface PerformanceResourceTimingStarted : PerformanceEntry {} type that is created when a resource fetch has been initiated. Then we colud use a PerformanceObserver to listen to those types. It could possibly be linked to the final PerformanceResourceTiming entry .

nicjansma commented 9 years ago

I took a quick look at the Fetch registry proposal, and while I think it could potentially be used to determine if there are any outstanding network fetches (if it exposes the appropriate data via JS), there's no talk of having a notification event about new entries. Ideally I'd like there to be an event so we don't have to poll. That's one of the reasons I think the PerformanceObserver interface would be so ideal for this.

I see a couple options:

  1. Add PerformanceResourceTiming entries when the resource starts to fetch, not when it's completed
    • Downsides: Most consumers are probably only interested in when the entry completes. The PerformanceTimeline spec currently talks about returning copies of entries (not live ones that updated timestamps as the rest of the phases complete).
  2. Fire a PerformanceResourceTiming entry both when it starts and when it stops
    • Downsides: Consumers would have to filter to events they care about (start vs stop). Consumers may get confused if they don't fully read the docs to see that each fetch will appear twice (start then stop).
  3. Have a new PerformanceResourceTimingStarted event fire instead
    • Downsides: Seems a little wonky to create a special new entry type for this use case. Would probably need an attribute to link to the corresponding PerformanceResourceTiming entry (same as for PerformanceServerTiming).
  4. Similarly, have Fetch registry use PerformanceObserver and add PerformanceFetch entry type that fires when a fetch starts. Might be confusing to have a PerformanceFetch and PerformanceResourceTiming type though.
  5. Add an event to the Fetch registry

No strong opinion on which is best, but number 3 seems the most straightforward.

plehegar commented 9 years ago

adding @annevk since it interacts with fetch

annevk commented 9 years ago

@nicjansma we could eventually have events I suppose. We should if we expose it as an API. The shape of that API is still unclear though. Perhaps some kind of observer similar to DOM observers is better.

igrigorik commented 9 years ago

@nicjansma if we were to solve this within perf-timeline, then (3) seems most reasonable to me. Intuitively, I think of this as "mark" vs "measure": a task may have many marks, and at the end it emits a measure which captures all/some of the emitted marks as a "summary". For example a resource fetch may emit marks for each milestone (dns, tcp, etc), and then a summary record at the end.

That said, for this particular case of knowing when a new request has started, it does seem that proposed registry would be sufficient.

nicjansma commented 9 years ago

@igrigorik I like that analogy. (3) sounds good to me.

igrigorik commented 9 years ago

@nicjansma to clarify, I'm saying (3) seems like the most reasonable if we want to solve this as a general problem within perf timeline. But, for the particular use case of notifications of new fetches, it seems that registry solution is sufficient.

So, the open question now is whether we have concrete and high-value use cases for pursuing (3).

nicjansma commented 9 years ago

The three main use cases I've come up with give third-party scripts insight into an app's network activity without invasive instrumentation:

  1. Busy indicator: A widget could determine if there is any network activity outstanding on the page and provide a "spinner" icon or other visual "something is happening" feedback.
  2. Performance monitoring: A RUM solution could monitor network fetches that are still outstanding during the onload event and change its behavior based on that info.
  3. Providing an 'onload' for SPAs: Since onload no longer matters in a Single Page App (for hard or soft navigations), knowing if there are outstanding network requests can tell perf monitoring scripts if they should "wait" for more resources to finish to call a SPA navigation "done".
igrigorik commented 9 years ago

@nicjansma thanks. I think all of those are addressable via the registry, correct? FWIW, see:

nicjansma commented 9 years ago

@igrigorik Looks good

hiikezoe commented 9 years ago

What about Frame Timing? We should discuss in a new issue?

igrigorik commented 9 years ago

@hiikezoe yes, for FT specifically we should address the when question in that spec.

For general "when buffered events are delivered", let's continue the discussion in: https://github.com/w3c/performance-timeline/pull/46