Performance Timeline Level 2

W3C Working Draft

This version:
http://www.jbjac.tw/TR/2019/WD-performance-timeline-2-20190626/
Latest published version:
http://www.jbjac.tw/TR/performance-timeline-2/
Latest editor's draft:
https://w3c.github.io/performance-timeline/
Test suite:
https://github.com/web-platform-tests/wpt/tree/master/performance-timeline
Previous version:
http://www.jbjac.tw/TR/2019/WD-performance-timeline-2-20190423/
Editor:
(Google)
Former editors:
(Microsoft Corp.) (Until November 2014)
Zhiheng Wang (Google) (Until July 2013)
Participate:
GitHub w3c/performance-timeline
File a bug
Commit history
Pull requests

Abstract

This specification extends the High Resolution Time specification [HR-TIME-2] by providing methods to store and retrieve high resolution performance metric data.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.jbjac.tw/TR/.

Performance Timeline Level 2 replaces the first version of [PERFORMANCE-TIMELINE] and includes:

This document was published by the Web Performance Working Group as a Working Draft. This document is intended to become a W3C Recommendation.

GitHub Issues are preferred for discussion of this specification.

Publication as a Working Draft does not imply endorsement by the W3C Membership. 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 1 March 2019 W3C Process Document.

1. Introduction

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="http://www.jbjac.tw/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="http://www.jbjac.tw/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>

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.

2. Conformance

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).

3. Performance Timeline

Each ECMAScript global environment has:

In order to get the relevant performance entry tuple, given entryType as input, run the following steps:

  1. Let map be the performance entry buffer map associated with the relevant global object of the context object.
  2. Return the value returned when getting the value of an entry, given entryType as key.

3.1 Extensions to the Performance interface

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.

3.1.1 getEntries() method

Returns a PerformanceEntryList object returned by the filter buffer map by name and type algorithm with name and type set to null.

3.1.2 getEntriesByType() method

Returns a PerformanceEntryList object returned by filter buffer map by name and type algorithm with name set to null, and type set to the method's input type parameter.

3.1.3 getEntriesByName() method

Returns a PerformanceEntryList object returned by filter buffer map by name and type algorithm with 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.

4. The PerformanceEntry interface

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();
};
name
This attribute MUST return an identifier for this PerformanceEntry object. This identifier does not have to be unique.
entryType
This attribute MUST return the type of the interface represented by this PerformanceEntry object.
Note

Example entryType values defined by other specifications include: "mark" and "measure" [USER-TIMING-2], "navigation" [NAVIGATION-TIMING-2], "resource" [RESOURCE-TIMING-2], and "longtask".

startTime
This attribute MUST return the time value of the first recorded timestamp of this performance metric. If the startTime concept doesn't apply, a performance metric may choose to return a startTime of 0.
duration
This attribute MUST return the time value of the duration of the entire event being recorded by this 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.

When toJSON is called, run [WebIDL]'s default toJSON operation.

5. The PerformanceObserver interface

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 is a struct consisting of an observer member (a PerformanceObserver object) and an options list member (a list of PerformanceObserverInit dictionaries).

callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries,
                                             PerformanceObserver observer);
[Constructor(PerformanceObserverCallback callback), Exposed=(Window,Worker)]
interface PerformanceObserver {
  void observe (optional PerformanceObserverInit options);
  void disconnect ();
  PerformanceEntryList takeRecords();
  [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
};
Note

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.

5.1 observe() method

The observe() method instructs the user agent to register the observer and must run these steps:

  1. Let observer be the context object.
  2. Let relevantGlobal be observer's relevant global object.
  3. If options's entryTypes and type members are both omitted, then throw a SyntaxError.
  4. If options's entryTypes is present and any other member is also present, then throw a SyntaxError.
  5. Update or check observer's observer type by running these steps:
    1. If observer's observer type is "undefined":
      1. If options's entryTypes member is present, then set observer's observer type to "multiple".
      2. If options's type member is present, then set observer's observer type to "single".
    2. If observer's observer type is "single" and options's entryTypes member is present, then throw an InvalidModificationError.
    3. If observer's observer type is "multiple" and options's type member is present, then throw an InvalidModificationError.
  6. If observer's observer type is "multiple", run the following steps:
    1. Let entry types be options's entryTypes sequence.
    2. Remove all types from entry types that are not contained in relevantGlobal's frozen array of supported entry types. The user agent SHOULD notify developers if entry types is modified. For example, a console warning listing removed types might be appropriate.
    3. If the resulting entry types sequence is an empty sequence, abort these steps. The user agent SHOULD notify developers when the steps are aborted to notify that registration has been aborted. For example, a console warning might be appropriate.
    4. If the list of registered performance observer objects of relevantGlobal contains a registered performance observer whose observer is the context object, replace its options list with a list containing options as its only item.
    5. Otherwise, create and append a registered performance observer object to the list of registered performance observer objects of relevantGlobal, with observer set to the context object and options list set to a list containing options as its only item.
  7. Otherwise, run the following steps:
    1. Assert that observer's observer type is "single".
    2. If options's 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.
    3. If the list of registered performance observer objects of relevantGlobal contains a registered performance observer obs whose observer is the context object:
      1. If obs's options list contains a PerformanceObserverInit item currentOptions whose type is equal to options's type, replace currentOptions with options in obs's options list.
      2. Otherwise, append options to obs's options list.
    4. Otherwise, create and append a registered performance observer object to the list of registered performance observer objects of relevantGlobal, with observer set to the context object and options list set to a list containing options as its only item.
    5. If options's buffered flag is set:
      1. Let tuple be the relevant performance entry tuple given options's type as entryType.
      2. For each entry in tuple's performance entry buffer append entry to the observer buffer.
Note

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.

5.1.1 PerformanceObserverInit dictionary

dictionary PerformanceObserverInit {
  sequence<DOMString> entryTypes;
  DOMString type;
  boolean buffered;
};
entryTypes
A list of entry types to be observed. If present, the list MUST NOT be empty and all other members MUST NOT be present. Types not recognized by the user agent MUST be ignored.
type
A single entry type to be observed. A type that is not recognized by the user agent MUST be ignored. Other members may be present.
buffered
A flag to indicate whether buffered entries should be queued into observer's buffer.

5.1.2 PerformanceObserverEntryList interface

[Exposed=(Window,Worker)]
interface PerformanceObserverEntryList {
  PerformanceEntryList getEntries();
  PerformanceEntryList getEntriesByType (DOMString type);
  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
};
5.1.2.1 getEntries() method

Returns a PerformanceEntryList object returned by filter buffer by name and type algorithm with the context object's observer buffer, name and type set to null.

5.1.2.2 getEntriesByType() method

Returns a PerformanceEntryList object returned by filter buffer by name and type algorithm with the context object's observer buffer, name set to null, and type set to the method's input type parameter.

5.1.2.3 getEntriesByName() method

Returns a PerformanceEntryList object returned by filter buffer by name and type algorithm with the context object's observer buffer, 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.

5.2 takeRecords() method

The takeRecords() method must return a copy of the context object's observer buffer, and also empty context object's observer buffer.

5.3 disconnect() method

The disconnect() method must remove the context object from the list of registered performance observer objects of relevant global object, and also empty context object's observer buffer.

5.4 supportedEntryTypes attribute

Each 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:

  1. Let globalObject be the environment settings object's global object.
  2. Return globalObject's frozen array of supported entry types.
Note

This attribute allows web developers to easily know which entry types are supported by the user agent.

6. Processing

6.1 Queue a PerformanceEntry

To queue a PerformanceEntry (new entry), run these steps:

  1. Let interested observers be an initially empty set of PerformanceObserver objects.
  2. Let entryType be new entry’s entryType value.
  3. For each registered performance observer (regObs):
    1. If regObs's options list contains a PerformanceObserverInit item whose entryTypes member includes entryType or whose type member equals to entryType, append regObs's observer to interested observers.
  4. For each observer in interested observers:
    1. Append new entry to observer's observer buffer.
  5. Call the determine eligibility for adding a performance entry algorithm with tuple set to the relevant performance entry tuple given entryType. If it returns true, append new entry to tuple's performance entry buffer.
  6. If the performance observer task queued flag is set, terminate these steps.
  7. Set performance observer task queued flag.
  8. Queue a task that consists of running the following substeps. The task source for the queued task is the performance timeline task source.
    1. Unset performance observer task queued flag for the relevant global object.
    2. Let notify list be a copy of relevant global object's list of registered performance observer objects.
    3. For each PerformanceObserver object po in notify list, run these steps:
      1. Let entries be a copy of po’s observer buffer.
      2. Empty po’s observer buffer.
      3. If entries is non-empty, call po’s callback with entries as first argument and po as the second argument and callback this value. If this throws an exception, report the exception.

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.

6.2 Filter buffer map by name and type

When asked to run the filter buffer map by name and type algorithm with optional name and type, run the following steps:

  1. Let result be an initially empty list.
  2. Let map be the performance entry buffer map associated with the relevant global object of context object.
  3. Let tuple list be an empty list.
  4. If type is not null, append the result of getting the value of entry on map given type as key to tuple list. Otherwise, assign the result of get the values on map to tuple list
  5. For each tuple in tuple list, run the following steps:
    1. Let buffer be tuple's performance entry buffer.
    2. If tuple's availableFromTimeline is false, continue to the next tuple.
    3. Let entries be the result of running filter buffer by name and type with buffer, name and type as inputs.
    4. For each entry in entries, append entry to result.
  6. Sort results's entries in chronological order with respect to startTime
  7. Return result.

6.3 Filter buffer by name and type

When asked to run the filter buffer by name and type algorithm, with buffer, name, and type as inputs, run the following steps:

  1. Let result be an initially empty list.
  2. For each PerformanceEntry entry in buffer, run the following steps:
    1. If type is not null and if type does not match entry's entryType attribute in a case-sensitive manner, continue to next entry.
    2. If name is not null and if name does not match entry's name attribute in a case-sensitive manner, continue to next entry.
    3. append entry to result.
  3. Sort results's entries in chronological order with respect to startTime
  4. Return result.

6.4 Eligibility for adding a PerformanceEntry to a buffer

To determine eligibility for adding a performance entry, with required performance entry tuple, run the following steps:

  1. Let num current entries be the size of tuple's performance entry buffer.
  2. If num current entries is less than tuples's maxBufferSize, return true.
  3. Return false.

7. Privacy and Security

This 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.

8. Dependencies

The [HR-TIME] specification defines the DOMHighResTimeStamp interface.

The [INFRA] specification defines the following: append, key, value, getting the value of an entry.

The [HTML] specification defines the following: task queue.

The [WebIDL] specification defines the following: SyntaxError, ECMAScript global environment, InvalidModificationError.

A. IDL Index

partial interface Performance {
  PerformanceEntryList getEntries ();
  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;
  [Default] object toJSON();
};

callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries,
                                             PerformanceObserver observer);
[Constructor(PerformanceObserverCallback callback), Exposed=(Window,Worker)]
interface PerformanceObserver {
  void observe (optional PerformanceObserverInit options);
  void disconnect ();
  PerformanceEntryList takeRecords();
  [SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes;
};

dictionary PerformanceObserverInit {
  sequence<DOMString> entryTypes;
  DOMString type;
  boolean buffered;
};

[Exposed=(Window,Worker)]
interface PerformanceObserverEntryList {
  PerformanceEntryList getEntries();
  PerformanceEntryList getEntriesByType (DOMString type);
  PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type);
};

B. Acknowledgments

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.

C. References

C.1 Normative references

[dom]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[HR-TIME]
High Resolution Time. Jatinder Mann. W3C. 17 December 2012. W3C Recommendation. URL: http://www.jbjac.tw/TR/hr-time/
[HR-TIME-2]
High Resolution Time Level 2. Ilya Grigorik; James Simonsen; Jatinder Mann. W3C. 1 March 2018. W3C Candidate Recommendation. URL: http://www.jbjac.tw/TR/hr-time-2/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip J?genstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://tools.ietf.org/html/rfc8174
[WebIDL]
Web IDL. Boris Zbarsky. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/

C.2 Informative references

[NAVIGATION-TIMING-2]
Navigation Timing Level 2. Ilya Grigorik; Tobin Titus; Jatinder Mann; Arvind Jain. W3C. 8 March 2019. W3C Working Draft. URL: http://www.jbjac.tw/TR/navigation-timing-2/
[PERFORMANCE-TIMELINE]
Performance Timeline. Jatinder Mann; Zhiheng Wang. W3C. 12 December 2013. W3C Recommendation. URL: http://www.jbjac.tw/TR/performance-timeline/
[RESOURCE-TIMING-2]
Resource Timing Level 2. Todd Reifsteck; Ilya Grigorik; Yoav Weiss; Arvind Jain; Jatinder Mann; Zhiheng Wang; Anderson Quach. W3C. 26 June 2019. W3C Working Draft. URL: http://www.jbjac.tw/TR/resource-timing-2/
[USER-TIMING-2]
User Timing Level 2. Ilya Grigorik. W3C. 26 February 2019. W3C Recommendation. URL: http://www.jbjac.tw/TR/user-timing-2/
[WORKERS]
Web Workers. Ian Hickson. W3C. 24 September 2015. W3C Working Draft. URL: http://www.jbjac.tw/TR/workers/
1000炮金蟾捕鱼游戏机打法 英国5分彩开奖结果记录 七星彩如何网上买 秒速时时走势分析图 台湾五分彩走势图怎么看 广东时时官网下载 彩票中奖 吉林时时空 福彩30选5 广西快乐十分福彩选号器 任九场胜负彩开奖结果