Copyright © 2023 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
This specification extends the High Resolution Time specification [HR-TIME-3] by providing methods to store and retrieve high resolution performance metric data.
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
This Performance Timeline specification replaces the first version of [PERFORMANCE-TIMELINE] and includes:
Performance
interface defined by [HR-TIME-3]; PerformanceEntry
in Web Workers [WORKERS]; PerformanceObserver
. This document was published by the Web Performance Working Group as an Editor's Draft.
Publication as an Editor's Draft does not imply endorsement by W3C and its Members.
This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 2 November 2021 W3C Process Document.
This section is non-normative.
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.
The PerformanceObserver
interface was added 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. The observer works by specifying a callback in the constructor and specifying the performance entries it's interested in via the observe()
method. The user agent chooses when to execute the callback, which receives performance entries that have been queued.
There are special considerations regarding initial page load when using the PerformanceObserver
interface: a registration must be active to receive events but the registration script may not be available or may not be desired in the critical path. To address this, user agents buffer some number of events while the page is being constructed, and these buffered events can be accessed via the buffered
flag when registering the observer. When this flag is set, the user agent retrieves and dispatches events that it has buffered, for the specified entry type, and delivers them in the first callback after the observe()
call occurs.
The number of buffered events is determined by the specification that defines the metric and buffering is intended to used for first-N events only; buffering is not unbounded or continuous.
<!doctype html> <html> <head></head> <body> <img id="image0" src="https://www.w3.org/Icons/w3c_main.png" /> <script> // Know when the entry types we would like to use are not supported. function detectSupport(entryTypes) { for (const entryType of entryTypes) { if (!PerformanceObserver.supportedEntryTypes.includes(entryType)) { // Indicate to client-side analytics that |entryType| is not supported. } } } detectSupport(["resource", "mark", "measure"]); const userTimingObserver = 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); // Disconnect after processing the events. userTimingObserver.disconnect(); }); // Subscribe to new events for User-Timing. userTimingObserver.observe({entryTypes: ["mark", "measure"]}); const resourceObserver = new PerformanceObserver(list => { list .getEntries() // Get the values we are interested in .map(({ name, startTime, fetchStart, responseStart, responseEnd }) => { const obj = { "Name": name, "Start Time": startTime, "Fetch Start": fetchStart, "Response Start": responseStart, "Response End": responseEnd, }; return JSON.stringify(obj, null, 2); }) // Display them to the console. .forEach(console.log); // Disconnect after processing the events. resourceObserver.disconnect(); }); // Retrieve buffered events and subscribe to newer events for Resource Timing. resourceObserver.observe({type: "resource", buffered: true}); </script> </body> </html>
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MUST, MUST NOT, and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
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).
Each global object has:
DOMString
, representing the entry type to which the buffer belongs. The map's value is the following tuple: PerformanceEntry
objects, that is initially empty. boolean
availableFromTimeline, initialized to the registry value for this entry type. In order to get the relevant performance entry tuple, given entryType and globalObject as input, run the following steps:
Performance
interfaceThis extends the Performance
interface from [HR-TIME-3] and hosts performance related attributes and methods used to retrieve the performance metric data from the Performance Timeline.
WebIDLdictionary PerformanceEntryOptions
{ DOMString type
; DOMString name
; boolean includeFrames
; }; partial interface Performance { PerformanceEntryList
getEntries
(optional PerformanceEntryOptions
options = {}); 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.
type
name
includeFrames
Returns a PerformanceEntryList
object returned by the filter buffer map by name and type algorithm with name, type and includeFrames set to the corresponding members of the method's input options
parameter.
Returns a PerformanceEntryList
object returned by filter buffer map by name and type algorithm with name set to null
, type set to the method's input type
parameter, and includeFrames set to false
.
Returns a PerformanceEntryList
object returned by filter buffer map by name and type algorithm with name set to the method's input name
parameter, type set to either null
if optional entryType
is omitted, or the method's input type
parameter otherwise, and includeFrames set to false
.
The PerformanceEntry
interface hosts the performance data of various metrics.
WebIDL[Exposed=(Window,Worker)] interface PerformanceEntry
{ readonly attribute DOMString name
; readonly attribute DOMString entryType
; readonly attribute DOMHighResTimeStamp startTime
; readonly attribute DOMHighResTimeStamp duration
; readonly attribute object? source
; [Default] object toJSON
(); };
name
PerformanceEntry
object. This identifier does not have to be unique. entryType
PerformanceEntry
object. All entryType
values are defined in the relevantregistry. Examples include: "mark"
and "measure"
[USER-TIMING-2], "navigation"
[NAVIGATION-TIMING-2], "resource"
[RESOURCE-TIMING-2], and "longtask"
.
startTime
startTime
of 0
.duration
PerformanceEntry
. Typically, this would be the time difference between the last recorded timestamp and the first recorded timestamp of this PerformanceEntry
. If the duration concept doesn't apply, a performance metric may choose to return a duration
of 0
. source
PerformanceEntry
was recorded. When toJSON
is called, run [WebIDL]'s default toJSON steps.
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:
PerformanceObserverCallback
observer callback set on creation. PerformanceEntryList
object called the observer buffer that is initially empty. DOMString
observer type which is initially "undefined"
.The PerformanceObserver(callback)
constructor must create a new PerformanceObserver
object with its observer callback set to callback and then return it.
A registered performance observer is a struct consisting of an observer member (a PerformanceObserver
object) and an options list member (a list of PerformanceObserverInit
dictionaries).
WebIDLcallback PerformanceObserverCallback
= undefined (PerformanceObserverEntryList
entries, PerformanceObserver
observer, optional PerformanceObserverCallbackOptions
options = {}); [Exposed=(Window,Worker)] interface PerformanceObserver
{ constructor
(PerformanceObserverCallback
callback); undefined observe
(optional PerformanceObserverInit
options = {}); undefined disconnect
(); PerformanceEntryList
takeRecords
(); [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes
; };
To keep the performance overhead to minimum the application ought to 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.
WebIDLdictionary PerformanceObserverCallbackOptions
{ unsigned long long droppedEntriesCount
; };
droppedEntriesCount
PerformanceObserver
's requires dropped entries is set.The observe()
method instructs the user agent to register the observer and must run these steps:
entryTypes
and type
members are both omitted, then throw a "TypeError
". entryTypes
is present and any other member is also present, then throw a "TypeError
". "undefined"
: entryTypes
member is present, then set this's observer type to "multiple"
. type
member is present, then set this's observer type to "single"
. "single"
and options's entryTypes
member is present, then throw an "InvalidModificationError
". "multiple"
and options's type
member is present, then throw an "InvalidModificationError
". "multiple"
, run the following steps: entryTypes
sequence. "single"
. type
is not contained in the relevantGlobal's frozen array of supported entry types, abort these steps. The user agent SHOULD notify developers when this happens, for instance via a console warning. PerformanceObserverInit
item currentOptions whose type
is equal to options's type
, replace currentOptions with options in obs's options list. buffered
flag is set: type
and relevantGlobal. For each entry in tuple's performance entry buffer:
A PerformanceObserver
object needs to always call observe()
with options's entryTypes
set OR always call observe()
with options's type
set. If one PerformanceObserver
calls observe()
with entryTypes
and also calls observe with type
, then an exception is thrown. This is meant to avoid confusion with how calls would stack. When using entryTypes
, no other parameters in PerformanceObserverInit
can be used. In addition, multiple observe()
calls will override for backwards compatibility and because a single call should suffice in this case. On the other hand, when using type
, calls will stack because a single call can only specify one type. Calling observe()
with a repeated type
will also override.
WebIDLdictionary PerformanceObserverInit
{ sequence<DOMString> entryTypes
; DOMString type
; boolean buffered
; boolean includeFrames
; };
entryTypes
type
buffered
includeFrames
WebIDL[Exposed=(Window,Worker)] interface PerformanceObserverEntryList
{ PerformanceEntryList
getEntries
(); PerformanceEntryList
getEntriesByType
(DOMString type); PerformanceEntryList
getEntriesByName
(DOMString name, optional DOMString type); };
Each PerformanceObserverEntryList
object has an associated entry list, which consists of a PerformanceEntryList
and is initialized upon construction.
Returns a PerformanceEntryList
object returned by filter buffer by name and type algorithm with this's entry list, name and type set to null
.
Returns a PerformanceEntryList
object returned by filter buffer by name and type algorithm with this's entry list, name set to null
, and type set to the method's input type
parameter.
Returns a PerformanceEntryList
object returned by filter buffer by name and type algorithm with this's entry list, name set to the method input name
parameter, and type set to null
if optional entryType
is omitted, or set to the method's input type
parameter otherwise.
The takeRecords()
method must return a copy of this's observer buffer, and also empty this's observer buffer.
The disconnect()
method must do the following:
supportedEntryTypes
attributeEach global object has an associated frozen array of supported entry types, which is initialized to the FrozenArray created from the sequence of strings among the registry that are supported for the global object, in alphabetical order.
When supportedEntryTypes
's attribute getter is called, run the following steps:
This attribute allows web developers to easily know which entry types are supported by the user agent.
To queue a PerformanceEntry (newEntry) with optional boolean traverse, run these steps:
PerformanceObserver
objects. entryType
value. source
to relevantGlobal. If regObs's options list contains a PerformanceObserverInit
options whose entryTypes
member includes entryType or whose type
member equals to entryType:
share-performance-timeline-with
` and relevantGlobal's active document.*
, or origins contains context's origin, Queue a global task on the performance timeline task source with context's active window to queue a PerformanceEntry with newEntry.When asked to queue the PerformanceObserver task, given relevantGlobal as input, run the following steps:
PerformanceObserverEntryList
, with its entry list set to entries. PerformanceObserverInit
item in registeredObserver's options list: type
or in item's entryTypes
: PerformanceObserverCallbackOptions
with its droppedEntriesCount
set to droppedEntriesCount if droppedEntriesCount is not null, otherwise unset.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.
When asked to run the filter buffer map by name and type algorithm with optional name, type, and includeFrames, run the following steps:
startTime
When asked to run the filter buffer by name and type algorithm, with buffer, name, type and includeFrames as inputs, run the following steps:
PerformanceEntry
entry in buffer, run the following steps: source
, continue to next entry. entryType
attribute, continue to next entry. name
attribute, continue to next entry. startTime
To determine if a performance entry buffer is full, with tuple as input, run the following steps:
This specification defines a configuration point with the name share-performance-timeline-with
. Its type is set
, and its default value is the empty set.
Set members must be strings representing origins, or the token *
, representing all origins.
This integration requires a currently-non-specified "set" type and "string" type in Document Policy.
This specification extends the Performance
interface defined by [HR-TIME-3] and provides methods to queue and retrieve entries from the performance timeline. Please refer to [HR-TIME-3] for privacy considerations of exposing high-resoluting timing information. Each new specification introducing new performance entries should have its own privacy considerations as well.
This specification extends the Performance
interface defined by [HR-TIME-3] and provides methods to queue and retrieve entries from the performance timeline. Please refer to [HR-TIME-3] for security considerations of exposing high-resoluting timing information. Each new specification introducing new performance entries should have its own security considerations as well.
The [INFRA] specification defines the following: key, getting the value of an entry.
WebIDLdictionary PerformanceEntryOptions
{ DOMString type
; DOMString name
; boolean includeFrames
; }; partial interface Performance { PerformanceEntryList
getEntries
(optional PerformanceEntryOptions
options = {}); PerformanceEntryList
getEntriesByType
(DOMString type); PerformanceEntryList
getEntriesByName
(DOMString name, optional DOMString type); }; typedef sequence<PerformanceEntry
> PerformanceEntryList
; [Exposed=(Window,Worker)] interface PerformanceEntry
{ readonly attribute DOMString name
; readonly attribute DOMString entryType
; readonly attribute DOMHighResTimeStamp startTime
; readonly attribute DOMHighResTimeStamp duration
; readonly attribute object? source
; [Default] object toJSON
(); }; callback PerformanceObserverCallback
= undefined (PerformanceObserverEntryList
entries, PerformanceObserver
observer, optional PerformanceObserverCallbackOptions
options = {}); [Exposed=(Window,Worker)] interface PerformanceObserver
{ constructor
(PerformanceObserverCallback
callback); undefined observe
(optional PerformanceObserverInit
options = {}); undefined disconnect
(); PerformanceEntryList
takeRecords
(); [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes
; }; dictionary PerformanceObserverCallbackOptions
{ unsigned long long droppedEntriesCount
; }; dictionary PerformanceObserverInit
{ sequence<DOMString> entryTypes
; DOMString type
; boolean buffered
; boolean includeFrames
; }; [Exposed=(Window,Worker)] interface PerformanceObserverEntryList
{ PerformanceEntryList
getEntries
(); PerformanceEntryList
getEntriesByType
(DOMString type); PerformanceEntryList
getEntriesByName
(DOMString name, optional DOMString type); };
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.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: