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 = "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:
- Avoid polling the timeline to detect new metrics
- Eliminate costly deduplication logic to identify new metrics
- Eliminate race conditions with other consumers that may want to manipulate the buffer
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 entryTypeof 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 >
2. Performance Timeline
Each global object has:
- a performance observer task queued flag
- a list of registered performance observer objects that is initially empty
-
a
performance
entry
buffer
map
ordered
map
,
keyed
on
a
DOMString, representing the entry type to which the buffer belongs. The ordered map ’s value is the following tuple:-
A
performance
entry
buffer
to
store
PerformanceEntryobjects, that is initially empty. - An integer maxBufferSize , initialized to the registry value for this entry type.
-
A
booleanavailableFromTimeline , initialized to the registry value for this entry type. - An integer dropped entries count that is initially 0.
-
A
performance
entry
buffer
to
store
- An integer last performance entry id that is initially set to a random integer between 100 and 10000.
Each
Document
has:
-
A
most
recent
navigation
,
which
is
a
PerformanceEntry, initially unset.
In order to get the relevant performance entry tuple , given entryType and globalObject as input, run the following steps:
- Let map be the performance entry buffer map associated with globalObject .
- Return the result of getting the value of an entry from map , given entryType as the key .
2.1.
Extensions
to
the
Performance
interface
This
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
.
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.
2.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
.
2.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.
2.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.
3.
The
PerformanceEntry
interface
The
PerformanceEntry
interface
hosts
the
performance
data
of
various
metrics.
[Exposed =(Window ,Worker )]interface {PerformanceEntry readonly attribute unsigned long long ;id readonly attribute DOMString ;name readonly attribute DOMString ;entryType readonly attribute DOMHighResTimeStamp ;startTime readonly attribute DOMHighResTimeStamp ;duration readonly attribute unsigned long long ; [navigationId Default ]object (); };toJSON
- name
-
This
attribute
must
return
the
value
it
is
initialized
to.
It
represents
an
identifier
for
this
PerformanceEntryobject. This identifier does not have to be unique. - entryType
-
This
attribute
must
return
the
value
it
is
initialized
to.
All
entryTypevalues are defined in the relevant registry . Examples include:"mark"and"measure"[USER-TIMING-2] ,"navigation"[NAVIGATION-TIMING-2] , and"resource"[RESOURCE-TIMING-2] . - startTime
- This attribute must return the value it is initialized to. It represents the time value of the first recorded timestamp of this performance metric.
- duration
-
The
getter
steps
for
the
durationattribute are to return 0 if this ’s end time is 0; otherwise this ’s end time - this ’sstartTime. - navigationId
- This attribute MUST return the value it is initialized to.
When toJSON is called, run [WEBIDL] ’s default toJSON steps .
A
PerformanceEntry
has
a
DOMHighResTimeStamp
end
time
,
initially
0.
To
initialize
a
PerformanceEntry
entry
given
a
DOMHighResTimeStamp
startTime
,
a
DOMString
entryType
,
a
DOMString
name
,
and
an
optional
DOMHighResTimeStamp
endTime
(default
0
):
- Assert: entryType is defined in the entry type registry .
-
Initialize
entry
’s
startTimeto startTime . -
Initialize
entry
’s
entryTypeto entryType . -
Initialize
entry
’s
nameto name . - Initialize entry ’s end time to endTime .
4.
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:
-
A
PerformanceObserverCallbackobserver callback set on creation. -
A
PerformanceEntryListobject called the observer buffer that is initially empty. -
A
DOMStringobserver type which is initially"undefined". - A boolean requires dropped entries which is initially set to false.
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).
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
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.
4.1.
PerformanceObserverCallbackOptions
dictionary
dictionary {PerformanceObserverCallbackOptions unsigned long long ; };droppedEntriesCount
- droppedEntriesCount
-
An
integer
representing
the
dropped
entries
count
for
the
entry
types
that
the
observer
is
observing
when
the
PerformanceObserver’s requires dropped entries is set.
4.2.
observe()
method
The
observe()
method
instructs
the
user
agent
to
register
the
observer
and
must
run
these
steps:
- Let relevantGlobal be this ’s relevant global object .
-
If
options
’s
entryTypesandtypemembers are both omitted, then throw a"TypeError". -
If
options
’s
entryTypesis present and any other member is also present, then throw a"TypeError". -
Update
or
check
this
’s
observer
type
by
running
these
steps:
-
If
this
’s
observer
type
is
"undefined":-
If
options
’s
entryTypesmember is present, then set this ’s observer type to"multiple". -
If
options
’s
typemember is present, then set this ’s observer type to"single".
-
If
options
’s
-
If
this
’s
observer
type
is
"single"and options ’sentryTypesmember is present, then throw an"InvalidModificationError". -
If
this
’s
observer
type
is
"multiple"and options ’stypemember is present, then throw an"InvalidModificationError".
-
If
this
’s
observer
type
is
- Set this ’s requires dropped entries to true.
-
If
this
’s
observer
type
is
"multiple", run the following steps:-
Let
entry
types
be
options
’s
entryTypessequence. - 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.
- 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.
- If the list of registered performance observer objects of relevantGlobal contains a registered performance observer whose observer is this , replace its options list with a list containing options as its only item.
- Otherwise, create and append a registered performance observer object to the list of registered performance observer objects of relevantGlobal , with observer set to this and options list set to a list containing options as its only item.
-
Let
entry
types
be
options
’s
-
Otherwise,
run
the
following
steps:
-
Assert
that
this
’s
observer
type
is
"single". -
If
options
’s
typeis 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. -
If
the
list
of
registered
performance
observer
objects
of
relevantGlobal
contains
a
registered
performance
observer
obs
whose
observer
is
this
:
-
If
obs
’s
options
list
contains
a
PerformanceObserverInititem currentOptions whosetypeis equal to options ’stype, replace currentOptions with options in obs ’s options list . - Otherwise, append options to obs ’s options list .
-
If
obs
’s
options
list
contains
a
- Otherwise, create and append a registered performance observer object to the list of registered performance observer objects of relevantGlobal , with observer set to this and options list set to a list containing options as its only item.
-
If
options
’s
bufferedflag is set:-
Let
tuple
be
the
relevant
performance
entry
tuple
of
options
’s
typeand relevantGlobal . -
For each entry in tuple ’s performance entry buffer :
- If should add entry with entry and options as parameters returns true, append entry to the observer buffer .
- Queue the PerformanceObserver task with relevantGlobal as input.
-
Let
tuple
be
the
relevant
performance
entry
tuple
of
options
’s
-
Assert
that
this
’s
observer
type
is
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.
4.2.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.
4.2.2.
PerformanceObserverEntryList
interface
[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.
4.2.2.1.
getEntries()
method
Returns
a
PerformanceEntryList
object
returned
by
filter
buffer
by
name
and
type
algorithm
with
this
’s
entry
list
,
name
and
type
set
to
null
.
4.2.2.2.
getEntriesByType()
method
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.
4.2.2.3.
getEntriesByName()
method
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.
4.3.
takeRecords()
method
The
takeRecords()
method
must
return
a
copy
of
this
’s
observer
buffer
,
and
also
empty
this
’s
observer
buffer
.
4.4.
disconnect()
method
The
disconnect()
method
must
do
the
following:
- Remove this from the list of registered performance observer objects of relevant global object .
- Empty this ’s observer buffer .
- Empty this ’s options list .
4.5.
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:
- Let globalObject be the environment settings object’s global object .
- Return globalObject ’s frozen array of supported entry types .
This attribute allows web developers to easily know which entry types are supported by the user agent.
5. Processing
5.1.
Queue
a
PerformanceEntry
To queue a PerformanceEntry ( newEntry ), run these steps:
-
If
newEntry
’s
idis unset:- Let id be the result of running generate an id for newEntry .
-
Set
newEntry
’s
idto id .
-
Let
interested
observers
be
an
initially
empty
set
of
PerformanceObserverobjects. -
Let
entryType
be
newEntry
’s
entryTypevalue. - Let relevantGlobal be newEntry ’s relevant global object .
-
If
relevantGlobal
has
an
associated
document
:
-
Set
newEntry
’s
navigationIdto the value of relevantGlobal ’s associated document ’s most recent navigation ’sid.
-
Set
newEntry
’s
-
Otherwise,
set
newEntry
’s
navigationIdto null. -
For
each
registered
performance
observer
regObs
in
relevantGlobal
’s
list
of
registered
performance
observer
objects
:
-
If regObs ’s options list contains a
PerformanceObserverInitoptions whoseentryTypesmember includes entryType or whosetypemember equals to entryType :- If should add entry with newEntry and options returns true, append regObs ’s observer to interested observers .
-
-
For
each
observer
in
interested
observers
:
- Append newEntry to observer ’s observer buffer .
- Let tuple be the relevant performance entry tuple of entryType and relevantGlobal .
- Let isBufferFull be the return value of the determine if a performance entry buffer is full algorithm with tuple as input.
- Let shouldAdd be the result of should add entry with newEntry as input.
- If isBufferFull is false and shouldAdd is true, append newEntry to tuple ’s performance entry buffer .
- Queue the PerformanceObserver task with relevantGlobal as input.
5.2.
Queue
a
navigation
PerformanceEntry
To queue a navigation PerformanceEntry ( newEntry ), run these steps:
- Let id be the result of running generate an id for newEntry .
- Let relevantGlobal be newEntry ’s relevant global object .
-
Set
newEntry
’s
idto id . -
Set
newEntry
’s
navigationIdto id . -
If
relevantGlobal
has
an
associated
document
:
- Set relevantGlobal ’s associated document ’s most recent navigation to newEntry .
- Queue a PerformanceEntry with newEntry as input.
5.3. Queue the PerformanceObserver task
When asked to queue the PerformanceObserver task , given relevantGlobal as input, run the following steps:
- If relevantGlobal ’s performance observer task queued flag is set, terminate these steps.
- Set relevantGlobal ’s performance observer task queued flag .
-
Queue
a
task
that
consists
of
running
the
following
substeps.
The
task
source
for
the
queued
task
is
the
performance
timeline
task
source
.
- Unset performance observer task queued flag of relevantGlobal .
- Let notifyList be a copy of relevantGlobal ’s list of registered performance observer objects .
-
For
each
registered
performance
observer
object
registeredObserver
in
notifyList
,
run
these
steps:
- Let po be registeredObserver ’s observer .
- Let entries be a copy of po ’s observer buffer .
- If entries is empty, return.
- Empty po ’s observer buffer .
-
Let
observerEntryList
be
a
new
PerformanceObserverEntryList, with its entry list set to entries . - Let droppedEntriesCount be null.
-
If
po
’s
requires
dropped
entries
is
set,
perform
the
following
steps:
- Set droppedEntriesCount to 0.
-
For
each
PerformanceObserverInititem in registeredObserver ’s options list :-
For
each
DOMStringentryType that appears either as item ’stypeor in item ’sentryTypes:- Let map be relevantGlobal ’s performance entry buffer map .
- Let tuple be the result of getting the value of entry on map given entryType as key .
- Increase droppedEntriesCount by tuple ’s dropped entries count .
-
For
each
- Set po ’s requires dropped entries to false.
-
Let
callbackOptions
be
a
PerformanceObserverCallbackOptionswith itsdroppedEntriesCountset to droppedEntriesCount if droppedEntriesCount is not null, otherwise unset. - Invoke po ’s observer callback with « observerEntryList , po , callbackOptions », "`report`", and po .
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.
5.4. 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:
- Let result be an initially empty list .
- Let map be the performance entry buffer map associated with the relevant global object of this .
- Let tuple list be an empty list .
- 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 .
-
For
each
tuple
in
tuple
list
,
run
the
following
steps:
- Let buffer be tuple ’s performance entry buffer .
- If tuple ’s availableFromTimeline is false, continue to the next tuple .
- Let entries be the result of running filter buffer by name and type with buffer , name and type as inputs.
- For each entry in entries , append entry to result .
-
Sort
results
’s
entries
in
chronological
order
with
respect
to
startTime - Return result .
5.5. 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:
- Let result be an initially empty list .
-
For
each
PerformanceEntryentry in buffer , run the following steps:-
If
type
is
not
null
and
if
type
is
not
identical
to
entry
’s
entryTypeattribute, continue to next entry . -
If
name
is
not
null
and
if
name
is
not
identical
to
entry
’s
nameattribute, continue to next entry . - append entry to result .
-
If
type
is
not
null
and
if
type
is
not
identical
to
entry
’s
-
Sort
results
’s
entries
in
chronological
order
with
respect
to
startTime - Return result .
5.6. Determine if a performance entry buffer is full
To determine if a performance entry buffer is full , with tuple as input, run the following steps:
- Let num current entries be the size of tuple ’s performance entry buffer .
- If num current entries is less than tuple ’s maxBufferSize , return false.
- Increase tuple ’s dropped entries count by 1.
- Return true.
5.7. Generate a Performance Entry id
When
asked
to
generate
an
id
for
a
PerformanceEntry
entry
,
run
the
following
steps:
- Let relevantGlobal be entry ’s relevant global object .
- Increase relevantGlobal ’s last performance entry id by a small number chosen by the user agent.
- Return relevantGlobal ’s last performance entry id .
A user agent may choose to increase the last performance entry id by a small random integer every time. A user agent must not pick a single global random integer and increase the last performance entry id of all global objects by that amount because this could introduce cross origin leaks.
The last performance entry id has an initial random value, and is increased by a small number chosen by the user agent instead of 1 to discourage developers from considering it as a counter of the number of entries that have been generated in the web application.
6. Privacy Considerations
This section is non-normative.
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.
The
last
performance
entry
id
is
deliberately
initialized
to
a
random
value,
and
is
incremented
by
another
small
value
every
time
a
new
PerformanceEntry
is
queued.
User
agents
may
choose
to
use
a
consistent
increment
for
all
users,
or
may
pick
a
different
increment
for
each
global
object
,
or
may
choose
a
new
random
increment
for
each
PerformanceEntry
.
However,
in
order
to
prevent
cross-origin
leaks,
and
ensure
that
this
does
not
enable
fingerprinting,
user
agents
must
not
just
pick
a
unique
random
integer,
and
use
it
as
a
consistent
increment
for
all
PerformanceEntry
objects
across
all
global
objects
.
7. Security Considerations
This section is non-normative.
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.
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.