Monitoring event latency today requires an event listener. This precludes measuring event latency early in page load, and adds unnecessary performance overhead.
This document provides a proposal for giving developers insight into all event latencies.
This proposal explains the minimal API required to solve the following use cases:
- Observe the queueing delay of input events before event handlers are registered.
- Measure combined event handler duration.
A polyfill approximately implementing this API can be found here.
To accomplish these goals, we introduce:
interface PerformanceEventTiming : PerformanceEntry {
// The type of event dispatched. E.g. "touchmove".
// Doesn't require an event listener of this type to be registered.
readonly attribute DOMString name;
// "event".
readonly attribute DOMString entryType;
// The event timestamp.
readonly attribute DOMHighResTimeStamp startTime;
// The start time of the operation during which the event was dispatched.
readonly attribute DOMHighResTimeStamp processingStart;
// The duration between when the operation during which the event was
// dispatched finished executing and |startTime|.
readonly attribute DOMHighResTimeStamp duration;
// Whether or not the event was cancelable.
readonly attribute boolean cancelable;
};
When beginning an operation which will dispatch an event event
, execute these steps:
- Let
newEntry
be a newPerformanceEventTiming
object. - Set
newEntry
'sname
attribute toevent.type
. - Set
newEntry
'sentryType
attribute to "event". - Set
newEntry
'sstartTime
attribute toevent.timeStamp
. - Set
newEntry
'sprocessingStart
attribute to the value returned byperformance.now()
. - Set
newEntry
'sduration
attribute to 0. - Set
newEntry
'scancelable
attribute toevent.cancelable
.
After the operation during which event
was dispatched, execute these steps:
- Set
newEntry.duration
to the value returned byperformance.now() - event.timeStamp
. - If
event.isTrusted
is true andnewEntry.duration
> 50:- Queue
newEntry
. - Add
newEntry
to the performance entry buffer.
- Queue
How should we handle cases where the operation during which the event was dispatched doesn't block javascript?
For example composited scrolling? I suspect behaving as though the duration is 0 is correct, but specifying this may prove tricky.
const performanceObserver = new PerformanceObserver((entries) => {
for (const entry of entries.getEntries()) {
console.log(entry);
}
});
performanceObserver.observe({entryTypes:['event']});