This specification extends the High Resolution Time specification [[!HR-TIME-2]] by providing methods to store and retrieve high resolution performance metric data.
Performance Timeline Level 2 replaces the first version of [[PERFORMANCE-TIMELINE]] and includes:
Accurately measuring performance characteristics of web applications is an important aspect of making web applications faster. This specification defines the necessary Performance Timeline primitives that enable web developers to access, instrument, and retrieve various performance metrics from the full lifecycle of a web application.
[[NAVIGATION-TIMING-2]], [[RESOURCE-TIMING-2]], and [[USER-TIMING-2]] are examples of specifications that define timing information related to the navigation of the document, resources on the page, and developer scripts, respectively. Together these and other performance interfaces define performance metrics that describe the Performance Timeline of a web application. For example, the following script shows how a developer can access the Performance Timeline to obtain performance metrics related to the navigation of the document, resources on the page, and developer scripts:
<!doctype html>
<html>
<head></head>
<body onload="init()">
<img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
<script>
function init() {
// see [[USER-TIMING-2]]
performance.mark("startWork");
doWork(); // Some developer code
performance.mark("endWork");
measurePerf();
}
function measurePerf() {
performance
.getEntries()
.map(entry => JSON.stringify(entry, null, 2))
.forEach(json => console.log(json));
}
</script>
</body>
</html>
Alternatively, the developer can observe the Performance Timeline and be notified of new performance metrics and, optionally, previously buffered performance metrics of specified type, via the PerformanceObserver interface:
<!doctype html>
<html>
<head></head>
<body>
<img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
<script>
const observer = new PerformanceObserver(list => {
list
.getEntries()
// Get the values we are interested in
.map(({ name, entryType, startTime, duration }) => {
const obj = {
"Duration": duration,
"Entry Type": entryType,
"Name": name,
"Start Time": startTime,
};
return JSON.stringify(obj, null, 2);
})
// Display them to the console
.forEach(console.log);
// maybe disconnect after processing the events.
observer.disconnect();
});
// retrieve buffered events and subscribe to new events
// for Resource-Timing and User-Timing
observer.observe({
entryTypes: ["resource", "mark", "measure"],
buffered: true
});
</script>
</body>
</html>
The PerformanceObserver interface was added in Performance Timeline Level 2 and is designed to address limitations of the buffer-based approach shown in the first example. By using the PerformanceObserver interface, the application can:
The developer is encouraged to use PerformanceObserver where possible. Further, new performance API's and metrics may only be available through the PerformanceObserver interface.
Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.)
The IDL fragments in this specification must be interpreted as required for [conforming IDL fragments], as described in the Web IDL specification. [[!WebIDL]]
Each ECMAScript global environment has:
This extends the Performance interface [[!HR-TIME-2]] and hosts performance related attributes and methods used to retrieve the performance metric data from the Performance Timeline.
partial interface Performance {
PerformanceEntryList getEntries ();
PerformanceEntryList getEntriesByType (DOMString type);
PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
};
typedef sequence<PerformanceEntry> PerformanceEntryList;
The PerformanceEntryList represents a sequence of PerformanceEntry, providing developers with all the convenience methods found on JavaScript arrays.
Returns a PerformanceEntryList object returned by algorithm with buffer set to performance entry buffer, and name and type set to `null`.
Returns a PerformanceEntryList object returned by algorithm with buffer set to performance entry buffer, name set to `null`, and type set to `type`.
Returns a PerformanceEntryList object returned by algorithm with buffer set to performance entry buffer, name set to `name`, and type set to `null` if optional `entryType` is omitted, and type set to `type` otherwise.
The PerformanceEntry interface hosts the performance data of various metrics.
[Exposed=(Window,Worker)]
interface PerformanceEntry {
readonly attribute DOMString name;
readonly attribute DOMString entryType;
readonly attribute DOMHighResTimeStamp startTime;
readonly attribute DOMHighResTimeStamp duration;
[Default] object toJSON();
};
Example `entryType` values defined by other
specifications include: "mark" and "measure"
[[USER-TIMING-2]], "navigation" [[NAVIGATION-TIMING-2]],
"resource" [[RESOURCE-TIMING-2]],
and "longtask".
0.0.When toJSON is called, run [[!WebIDL]]'s default toJSON operation.
The PerformanceObserver interface can be used to observe the Performance Timeline to be notified of new performance metrics as they are recorded, and optionally buffered performance metrics.
Each PerformanceObserver has these associated concepts:
The `PerformanceObserver(callback)` constructor must create a new PerformanceObserver object with PerformanceObserverCallback set to callback and then return it.
A registered performance observer consists of an observer (a PerformanceObserver object) and options (a PerformanceObserverInit dictionary).
callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries,
PerformanceObserver observer);
[Constructor(PerformanceObserverCallback callback), Exposed=(Window,Worker)]
interface PerformanceObserver {
void observe (PerformanceObserverInit options);
void disconnect ();
};
To keep the performance overhead to minimum the application should only subscribe to event types that it is interested in, and disconnect the observer once it no longer needs to observe the performance data. Filtering by name is not supported, as it would implicitly require a subscription for all event types — this is possible, but discouraged, as it will generate a significant volume of events.
The observe() method instructs the user agent to register the observer and must run these steps:
The disconnect() method must remove the context object from the list of PerformanceObserver objects associated with the ECMAScript global environment of the interface object, and also empty context object's observer buffer.
dictionary PerformanceObserverInit {
required sequence<DOMString> entryTypes;
boolean buffered = false;
};
[Exposed=(Window,Worker)]
interface PerformanceObserverEntryList {
PerformanceEntryList getEntries();
PerformanceEntryList getEntriesByType (DOMString type);
PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
};
Returns a PerformanceEntryList object returned by algorithm with buffer set to observer buffer, and name and type set to `null`.
Returns a PerformanceEntryList object returned by algorithm with buffer set to observer buffer, name set to `null`, and type set to `type`.
Returns a PerformanceEntryList object returned by algorithm with buffer set to observer buffer, name set to `name`, and type set to `null` if optional `entryType` is omitted, and type set to `type` otherwise.
PerformanceEntryTo queue a PerformanceEntry (new entry) with an optional add to performance entry buffer flag, which is unset by default, run these steps:
The performance timeline task queue is a low priority queue that, if possible, should be processed by the user agent during idle periods to minimize impact of performance monitoring code.
Given a buffer and optional name and type string values this algorithm returns a PerformanceEntryList object that contains a list of PerformanceEntry objects sorted in chronological order with respect to startTime; objects with the same startTime have unspecified ordering.
This specification depends on the following interfaces, attributes, concepts, and terms which are defined in their linked specifications.
Performance interfacePerformanceResourceTiming
interfaceThis specification extends the Performance interface defined by [[HR-TIME-2]] and provides methods to queue and retrieve entries from the performance timeline. Please refer to [[HR-TIME-2]] for privacy and security considerations of exposing high-resoluting timing information.
Thanks to Arvind Jain, Boris Zbarsky, Jatinder Mann, Nat Duca, Philippe Le Hegaret, Ryosuke Niwa, Shubhie Panicker, Todd Reifsteck, Yoav Weiss, and Zhiheng Wang, for their contributions to this work.