-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathindex.html
497 lines (492 loc) · 30.7 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
<!DOCTYPE html>
<html>
<head>
<title>User Timing</title>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<script src="https://www.w3.org/Tools/respec/respec-w3c" class="remove">
</script>
<script class="remove">
// (this is to make tidy happy)
// See http://www.w3.org/respec/ for ReSpec documentation.
var respecConfig = {
specStatus: 'ED',
shortName: 'user-timing',
editors: [{
name: "Nicolás Peña Moreno",
url: 'https://github.com/npm1',
company: 'Google',
companyURL: 'https://google.com/',
w3cid: '103755'
}],
formerEditors: [{
name: 'Ilya Grigorik',
url: 'https://www.igvita.com/',
company: 'Google',
companyURL: 'https://google.com/',
w3cid: '56102'
},
{
name: 'Jatinder Mann',
company: 'Microsoft Corp.',
note: 'Until February 2014',
email: 'jmann@microsoft.com',
w3cid: '44357'
},
{
name: 'Zhiheng Wang',
company: 'Google Inc.',
note: 'Until July 2013',
w3cid: '43685'
},
{
name: 'Anderson Quach',
company: 'Microsoft Corp.',
note: 'until March 2011',
w3cid: '45288'
}],
group:"webperf",
wgPublicList: 'public-web-perf',
subjectPrefix: '[UserTiming]',
testSuiteURI: "https://wpt.fyi/results/user-timing",
implementationReportURI: "https://wpt.fyi/results/user-timing",
crEnd: "2018-08-06",
previousMaturity: "WD",
github: "https://github.com/w3c/user-timing/",
otherLinks: [{
key: 'Implementation',
data: [{
value: 'Can I use User Timing?',
href: 'http://caniuse.com/#feat=user-timing'
}]
}],
// This is important for Rec-track documents, do not copy a patent URI
// from a random document unless you know what you're doing. If in
// doubt ask your friendly neighbourhood Team Contact.
xref: {
specs: ['infra']
},
};
</script>
</head>
<body>
<section id="abstract">
<p>This specification defines an interface to help web
developers measure the performance of their applications by giving them access
to high precision timestamps.</p>
</section>
<section id="sotd">
<p>This User Timing specification is intended to supersede [[USER-TIMING-2]] and includes:</p>
<ul>
<li>Ability to execute marks and measures across arbitrary timestamps.</li>
<li>Support for reporting arbitrary metadata along with marks and measures.</li>
</ul>
</section>
<section class="informative" id="introduction">
<h2>Introduction</h2>
<p>Web developers need the ability to assess and understand the performance characteristics of their applications. While JavaScript [[ECMA-262]] provides a mechanism to measure application latency (retrieving the current timestamp from the <code>Date.now()</code> method), the precision of this timestamp varies between user agents.</p>
<p>This document defines the <a>PerformanceMark</a> and <a>PerformanceMeasure</a> interfaces, and extensions to the <a href="#extensions-performance-interface"><code>Performance</code></a> interface, which expose a high precision, monotonically increasing timestamp so that developers can better measure the performance characteristics of their applications.</p>
<div class="informative">
<p>The following script shows how a developer can use the interfaces defined in this document to obtain timing data related to developer scripts.</p>
<pre class="example">
async function run() {
performance.mark("startTask1");
await doTask1(); // Some developer code
performance.mark("endTask1");
performance.mark("startTask2");
await doTask2(); // Some developer code
performance.mark("endTask2");
// Log them out
const entries = performance.getEntriesByType("mark");
for (const entry of entries) {
console.table(entry.toJSON());
}
}
run();
</pre>
<p class="note">[[PERFORMANCE-TIMELINE-2]] defines two mechanisms that
can be used to retrieve recorded metrics: <code>getEntries()</code>
and <code>getEntriesByType()</code> methods, and the
<code>PerformanceObserver</code> interface. The former is best suited
for cases where you want to retrieve a particular metric by name at a
single point in time, and the latter is optimized for cases where you
may want to receive notifications of new metrics as they become
available.</p>
<p>As another example, suppose that there is an element which, when
clicked, fetches some new content and indicates that it has been fetched.
We'd like to report the time from when the user clicked to when the fetch
was complete. We can't mark the time the click handler executes since that
will miss latency to process the event, so instead we use the event
hardware timestamp. We also want to know the name of the component to have
more detailed analytics.</p>
<pre class="example">
element.addEventListener("click", e => {
const component = getComponent(element);
fetch(component.url).then(() => {
element.textContent = "Updated";
const updateMark = performance.mark("update_component", {
detail: {component: component.name},
});
performance.measure("click_to_update_component", {
detail: {component: component.name},
start: e.timeStamp,
end: updateMark.startTime,
});
});
});
</pre>
</div>
</section>
<section id="conformance">
<p>Some conformance requirements are phrased as requirements on attributes,
methods or objects. Such requirements are to be interpreted as requirements
on user agents. </p>
<p>The IDL fragments in this specification MUST be interpreted as
required for conforming IDL fragments, as described in the Web IDL
specification. [[WEBIDL]]</p>
</section>
<section>
<h2>User Timing</h2>
<section id="extensions-performance-interface" data-dfn-for="Performance" data-link-for="Performance">
<h2>Extensions to the <code><dfn data-cite="HR-TIME-2#dfn-performance">Performance</dfn></code> interface</h2>
<p>The <a>Performance</a> interface and <dfn data-cite="hr-time-2#dom-domhighrestimestamp">DOMHighResTimeStamp</dfn> are defined in [[HR-TIME-2]].
The <dfn data-cite="PERFORMANCE-TIMELINE-2/#dom-performanceentry">PerformanceEntry</dfn> interface is defined in [[PERFORMANCE-TIMELINE-2]].
</p>
<pre class="idl">
dictionary PerformanceMarkOptions {
any detail;
DOMHighResTimeStamp startTime;
};
dictionary PerformanceMeasureOptions {
any detail;
(DOMString or DOMHighResTimeStamp) start;
DOMHighResTimeStamp duration;
(DOMString or DOMHighResTimeStamp) end;
};
partial interface Performance {
PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions = {});
undefined clearMarks(optional DOMString markName);
PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions = {}, optional DOMString endMark);
undefined clearMeasures(optional DOMString measureName);
};
</pre>
<section data-link-for="PerformanceMarkOptions">
<h2><dfn>mark()</dfn> method</h2>
<p>Stores a timestamp with the associated name (a "mark"). It MUST run these steps:</p>
<ol>
<li>Run the <a>PerformanceMark constructor</a> and let <var>entry</var> be the newly created object.</li>
<li><a data-cite="PERFORMANCE-TIMELINE-2#dfn-queue-a-performanceentry">Queue</a> <var>entry</var>.</li>
<li id="stored_mark">Add <var>entry</var> to the <a data-cite="PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer">performance entry buffer</a>.</li>
<li>Return <var>entry</var>.</li>
</ol>
<section data-dfn-for="PerformanceMarkOptions">
<h2><dfn>PerformanceMarkOptions</dfn> dictionary</h2>
<dl>
<dt><dfn>detail</dfn></dt>
<dd>Metadata to be included in the mark.</dd>
<dt><dfn>startTime</dfn></dt>
<dd>Timestamp to be used as the mark time.</dd>
</dl>
<dl>
</section>
</section>
<section>
<h2><dfn>clearMarks()</dfn> method</h2>
<p>Removes the stored timestamp with the associated name. It MUST run these steps:</p>
<ol>
<li>If <var>markName</var> is omitted, remove all <a>PerformanceMark</a> objects from the <a data-cite="PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer">performance entry buffer</a>.</li>
<li>Otherwise, remove all <a>PerformanceMark</a> objects listed in the <a data-cite="PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer">performance entry buffer</a> whose <var>name</var> [=string/is=] <var>markName</var>.</li>
<li>Return <strong>undefined</strong>.</li>
</ol>
</section>
<section data-link-for="PerformanceMeasureOptions">
<h2><dfn>measure()</dfn> method</h2>
<p>Stores the {{DOMHighResTimeStamp}} duration between two marks along with the associated name (a "measure"). It MUST run these steps:</p>
<ol>
<li>If <var>startOrMeasureOptions</var> is a <a>PerformanceMeasureOptions</a> object and at least one of <a>start</a>, <a>end</a>, <a>duration</a>, and <a>detail</a> [=map/exist=], run the following checks:
<ol>
<li>If <var>endMark</var> is given, <a data-cite="WEBIDL#dfn-throw">throw</a> a <a data-cite="WEBIDL#exceptiondef-typeerror"><code>TypeError</code></a>.</li>
<li>If <var>startOrMeasureOptions</var>'s <a>start</a> and <a>end</a> members are both omitted, <a data-cite="WEBIDL#dfn-throw">throw</a> a <a data-cite="WEBIDL#exceptiondef-typeerror"><code>TypeError</code></a>.</li>
<li>If <var>startOrMeasureOptions</var>'s <a>start</a>, <a>duration</a>, and <a>end</a> members all [=map/exist=], <a data-cite="WEBIDL#dfn-throw">throw</a> a <a data-cite="WEBIDL#exceptiondef-typeerror"><code>TypeError</code></a>.</li>
</ol>
</li>
<li>
Compute <var>end time</var> as follows:
<ol>
<li>If <var>endMark</var> is given, let <var>end time</var> be the value returned by running the <a>convert a mark to a timestamp</a> algorithm passing in <var>endMark</var>.</li>
<li>Otherwise, if <var>startOrMeasureOptions</var> is a <a>PerformanceMeasureOptions</a> object, and if its <a>end</a> member [=map/exists=], let <var>end time</var> be the value returned by running the <a>convert a mark to a timestamp</a> algorithm passing in <var>startOrMeasureOptions</var>'s <a>end</a>.</li>
<li>
Otherwise, if <var>startOrMeasureOptions</var> is a <a>PerformanceMeasureOptions</a> object, and if its <a>start</a> and <a>duration</a> members both [=map/exist=]:
<ol>
<li>Let <var>start</var> be the value returned by running the <a>convert a mark to a timestamp</a> algorithm passing in <a>start</a>.</li>
<li>Let <var>duration</var> be the value returned by running the <a>convert a mark to a timestamp</a> algorithm passing in <a>duration</a>.</li>
<li>Let <var>end time</var> be <var>start</var> plus <var>duration</var>.</li>
</ol>
</li>
<li>Otherwise, let <var>end time</var> be the value that would be returned by the <code>Performance</code> object's <a data-cite="HR-TIME-2#dom-performance-now"><code>now()</code></a> method.</li>
</ol>
</li>
<li>
Compute <var>start time</var> as follows:
<ol>
<li>If <var>startOrMeasureOptions</var> is a <a>PerformanceMeasureOptions</a> object, and if its <a>start</a> member [=map/exists=], let <var>start time</var> be the value returned by running the <a>convert a mark to a timestamp</a> algorithm passing in <var>startOrMeasureOptions</var>'s <a>start</a>.</li>
<li>
Otherwise, if <var>startOrMeasureOptions</var> is a <a>PerformanceMeasureOptions</a> object, and if its <a>duration</a> and <a>end</a> members both [=map/exist=]:
<ol>
<li>Let <var>duration</var> be the value returned by running the <a>convert a mark to a timestamp</a> algorithm passing in <a>duration</a>.</li>
<li>Let <var>end</var> be the value returned by running the <a>convert a mark to a timestamp</a> algorithm passing in <a>end</a>.</li>
<li>Let <var>start time</var> be <var>end</var> minus <var>duration</var>.</li>
</ol>
</li>
<li>Otherwise, if <var>startOrMeasureOptions</var> is a <code>DOMString</code>, let <var>start time</var> be the value returned by running the <a>convert a mark to a timestamp</a> algorithm passing in <var>startOrMeasureOptions</var>.</li>
<li>Otherwise, let <var>start time</var> be <code>0</code>.</li>
</ol>
</li>
<li>Create a new <a>PerformanceMeasure</a> object (<var>entry</var>) with <a data-cite="WEBIDL#this">this</a>'s <a data-cite="HTML/webappapis.html#concept-relevant-realm">relevant realm</a>.</li>
<li>Set <var>entry</var>'s <code>name</code> attribute to <var>measureName</var>.</li>
<li>Set <var>entry</var>'s <code>entryType</code> attribute to <code>DOMString "measure"</code>.</li>
<li>Set <var>entry</var>'s <code>startTime</code> attribute to <var>start time</var>.</li>
<li>Set <var>entry</var>'s <code>duration</code> attribute to the duration from <var>start time</var> to <var>end time</var>. The resulting duration value MAY be negative.</li>
<li>
Set <var>entry</var>'s <code>detail</code> attribute as follows:
<ol>
<li>If <var>startOrMeasureOptions</var> is a <a>PerformanceMeasureOptions</a> object and <var>startOrMeasureOptions</var>'s <a>detail</a> member [=map/exists=]:
<ol>
<li>Let <var>record</var> be the result of calling the <a data-cite="HTML/infrastructure.html#structuredserialize">StructuredSerialize</a> algorithm on <var>startOrMeasureOptions</var>'s <a>detail</a>.</li>
<li>Set <var>entry</var>'s <a data-link-for=PerformanceMeasure>detail</a> to the result of calling the <a data-cite="HTML/infrastructure.html#structureddeserialize">StructuredDeserialize</a> algorithm on <var>record</var> and the <a data-cite="HTML/webappapis.html#concept-current-everything">current realm</a>.</li>
</ol>
</li>
<li>Otherwise, set it to <code>null</code>.</li>
</ol>
</li>
<li><a data-cite="PERFORMANCE-TIMELINE-2#dfn-queue-a-performanceentry">Queue</a> <var>entry</var>.</li>
<li id="stored_measure">Add <var>entry</var> to the <a data-cite="PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer">performance entry buffer</a>.</li>
<li>Return <var>entry</var>.</li>
</ol>
<section data-dfn-for="PerformanceMeasureOptions">
<h2><dfn>PerformanceMeasureOptions</dfn> dictionary</h2>
<dl>
<dt><dfn>detail</dfn></dt>
<dd>Metadata to be included in the measure.</dd>
<dt><dfn>start</dfn></dt>
<dd>Timestamp to be used as the start time or string to be used as start mark.</dd>
<dt><dfn>duration</dfn></dt>
<dd>Duration between the start and end times.</dd>
<dt><dfn>end</dfn></dt>
<dd>Timestamp to be used as the end time or string to be used as end mark.</dd>
</dl>
<dl>
</section>
</section>
<section>
<h2><dfn>clearMeasures()</dfn> method</h2>
<p>Removes stored timestamp with the associated name. It MUST run these steps:</p>
<ol>
<li>If <var>measureName</var> is omitted, remove all <a>PerformanceMeasure</a> objects in the <a data-cite="PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer">performance entry buffer</a>.</li>
<li>Otherwise remove all <a>PerformanceMeasure</a> objects listed in the <a data-cite="PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer">performance entry buffer</a> whose <code>name</code> [=string/is=] <var>measureName</var>.</li>
<li>Return <strong>undefined</strong>.</li>
</ol>
</section>
</section>
<section id="performancemark" data-dfn-for="PerformanceMark" data-link-for="PerformanceMark">
<h2>The <dfn>PerformanceMark</dfn> Interface</h2>
<p>The <a>PerformanceMark</a> interface also exposes marks created via the {{Performance}} interface's {{Performance/mark()}} method to the <a data-cite="PERFORMANCE-TIMELINE-2#dfn-performance-timeline">Performance Timeline</a>.</p>
<pre class="idl">
[Exposed=(Window,Worker)]
interface PerformanceMark : PerformanceEntry {
constructor(DOMString markName, optional PerformanceMarkOptions markOptions = {});
readonly attribute any detail;
};
</pre>
<p>The <a>PerformanceMark</a> interface extends the following attributes of the {{PerformanceEntry}}
interface:</p>
<p>The <code>name</code> attribute must return the mark's name.</p>
<p>The <code>entryType</code> attribute must return the <a data-cite="WEBIDL#idl-DOMString"><code>DOMString</code></a> <code>"mark"</code>.</p>
<p>The <code>startTime</code> attribute must return a {{DOMHighResTimeStamp}} with the mark's time value.</p>
<p>The <code>duration</code> attribute must return a {{DOMHighResTimeStamp}} of value <code>0</code>.</p>
<p>The <a>PerformanceMark</a> interface contains the following additional attribute:</p>
<p>The <dfn>detail</dfn> attribute must return the value it is set to (it's copied from the <a>PerformanceMarkOptions</a> dictionary).</p>
<section data-link-for="PerformanceMarkOptions">
<h3>The <dfn><a>PerformanceMark</a> Constructor</dfn></h3>
<p>The <a>PerformanceMark constructor</a> must run the following steps:</p>
<ol>
<li>If the <a data-cite="HTML/webappapis.html#current-global-object">current global object</a> is a <code>Window</code> object and <var>markName</var> uses the same name as a <a data-cite="WEBIDL#dfn-read-only">read only attribute</a> in the <code><a data-cite="NAVIGATION-TIMING#performancetiming">PerformanceTiming</a></code> interface, <a data-cite="WEBIDL#dfn-throw">throw</a> a <a data-cite="WEBIDL#syntaxerror"><code>SyntaxError</code></a>.</li>
<li>Create a new <a>PerformanceMark</a> object (<var>entry</var>) with the <a data-cite="HTML/webappapis.html#current-global-object">current global object</a>'s <a data-cite="HTML/webappapis.html#concept-global-object-realm">realm</a>.</li>
<li>Set <var>entry</var>'s <code>name</code> attribute to <var>markName</var>.</li>
<li>Set <var>entry</var>'s <code>entryType</code> attribute to <code>DOMString "mark"</code>.</li>
<li>
Set <var>entry</var>'s <code>startTime</code> attribute as follows:
<ol>
<li>
If <var>markOptions</var>'s <a>startTime</a> member [=map/exists=], then:
<ol>
<li>If <var>markOptions</var>'s <a>startTime</a> is negative, throw a <a data-cite="WEBIDL#exceptiondef-typeerror"><code>TypeError</code></a>.</li>
<li>Otherwise, set <var>entry</var>'s <code>startTime</code> to the value of <var>markOptions</var>'s <a>startTime</a>.</li>
</ol>
</li>
<li>Otherwise, set it to the value that would be returned by the <code>Performance</code> object's <a data-cite="HR-TIME-2#dom-performance-now"><code>now()</code></a> method.</li>
</ol>
</li>
<li>Set <var>entry</var>'s <code>duration</code> attribute to <code>0</code>.</li>
<li>If <var>markOptions</var>'s <a>detail</a> is null, set <var>entry</var>'s <a data-link-for=PerformanceMark>detail</a> to null.</li>
<li>Otherwise:
<ol>
<li>Let <var>record</var> be the result of calling the <a data-cite="HTML/infrastructure.html#structuredserialize">StructuredSerialize</a> algorithm on <var>markOptions</var>'s <a>detail</a>.</li>
<li>Set <var>entry</var>'s <a data-link-for=PerformanceMark>detail</a> to the result of calling the <a data-cite="HTML/infrastructure.html#structureddeserialize">StructuredDeserialize</a> algorithm on <var>record</var> and the <a data-cite="HTML/webappapis.html#concept-current-everything">current realm</a>.</li>
</ol>
</li>
</ol>
</section>
</section>
<section id="performancemeasure" data-dfn-for="PerformanceMeasure" data-link-for="PerformanceMeasure">
<h2>The <dfn>PerformanceMeasure</dfn> Interface</h2>
<p>The <a>PerformanceMeasure</a> interface also exposes measures created via the {{Performance}} interface's {{Performance/measure()}} method to the <a data-cite="PERFORMANCE-TIMELINE-2#performance-timeline">Performance Timeline</a>.</p>
<pre class="idl">
[Exposed=(Window,Worker)]
interface PerformanceMeasure : PerformanceEntry {
readonly attribute any detail;
};
</pre>
<p>The <a>PerformanceMeasure</a> interface extends the following attributes of the {{PerformanceEntry}} interface:</p>
<p>The <code>name</code> attribute must return the measure's name.</p>
<p>The <code>entryType</code> attribute must return the <a data-cite="WEBIDL#idl-DOMString"><code>DOMString</code></a> <code>"measure"</code>.</p>
<p>The <code>startTime</code> attribute must return a {{DOMHighResTimeStamp}} with the measure's start mark.</p>
<p>The <code>duration</code> attribute must return a {{DOMHighResTimeStamp}} with the duration of the measure.</p>
<p>The <a>PerformanceMeasure</a> interface contains the following additional attribute:</p>
<p>The <dfn>detail</dfn> attribute must return the value it is set to (it's copied from the <a>PerformanceMeasureOptions</a> dictionary).</p>
</section>
</section>
<section>
<h2>Processing</h2>
<p class='note'>A user agent implementing the User Timing API would need to include <code>"mark"</code> and
<code>"measure"</code> in <a data-cite="PERFORMANCE-TIMELINE-2#supportedentrytypes-attribute">
supportedEntryTypes</a>. This allows developers to detect support for User Timing.</p>
<section>
<h2>Convert a <var>mark</var> to a <var>timestamp</var></h2>
<p>To <dfn>convert a mark to a timestamp</dfn>, given a <var>mark</var> that is a <code>DOMString</code> or {{DOMHighResTimeStamp}} run these steps:
<ol>
<li>If <var>mark</var> is a <code>DOMString</code> and it has the same name as a <a data-cite="WEBIDL#dfn-read-only">read only attribute</a> in the <code><a data-cite="NAVIGATION-TIMING#performancetiming">PerformanceTiming</a></code> interface, let <var>end time</var> be the value returned by running the <a>convert a name to a timestamp</a> algorithm with <var>name</var> set to the value of <var>mark</var>.</li>
<li>Otherwise, if <var>mark</var> is a <code>DOMString</code>, let <var>end time</var> be the value of the <code>startTime</code> attribute from the most recent occurrence of a <a>PerformanceMark</a> object in the <a data-cite="PERFORMANCE-TIMELINE-2#dfn-performance-entry-buffer">performance entry buffer</a> whose <code>name</code> [=string/is=] <var>mark</var>. If no matching entry is found, <a data-cite="WEBIDL#dfn-throw">throw</a> a <a data-cite="WEBIDL#syntaxerror"><code>SyntaxError</code></a>.</li>
<li>
Otherwise, if <var>mark</var> is a {{DOMHighResTimeStamp}}:
<ol>
<li>If <var>mark</var> is negative, throw a <a data-cite="WEBIDL#exceptiondef-typeerror"><code>TypeError</code></a>.</li>
<li>Otherwise, let <var>end time</var> be <var>mark</var>.</li>
</ol>
</li>
</ol>
</section>
<section>
<h2>Convert a <var>name</var> to a <var>timestamp</var></h2>
<p>To <dfn>convert a name to a <a data-cite="HR-TIME-2#idl-def-domhighrestimestamp">timestamp</a></dfn> given a <var>name</var> that is a <a data-cite="WEBIDL#dfn-read-only">read only attribute</a> in the <code><a data-cite="NAVIGATION-TIMING#performancetiming">PerformanceTiming</a></code> interface, run these steps:<p>
<ol>
<li>If the <a data-cite="HTML/webappapis.html#global-object">global object</a> is not a <code>Window</code> object, <a data-cite="WEBIDL#dfn-throw">throw</a> a <a data-cite="WEBIDL#exceptiondef-typeerror"><code>TypeError</code></a>.</li>
<li>If <var>name</var> is <code>navigationStart</code>, return <code>0</code>.</li>
<li>Let <var>startTime</var> be the value of <code>navigationStart</code> in the <code><a data-cite="NAVIGATION-TIMING#performancetiming">PerformanceTiming</a></code> interface.</li>
<li>Let <var>endTime</var> be the value of <var>name</var> in the <code><a data-cite="NAVIGATION-TIMING#performancetiming">PerformanceTiming</a></code> interface.</li>
<li>If <var>endTime</var> is <code>0</code>, <a data-cite="WEBIDL#dfn-throw">throw</a> an <a data-cite="WEBIDL#invalidaccesserror"><code>InvalidAccessError</code></a>.</li>
<li>Return result of subtracting <var>startTime</var> from <var>endTime</var>.</li>
</ol>
<p class="note">
The <a data-cite="NAVIGATION-TIMING#performancetiming">PerformanceTiming</a> interface was defined in [[NAVIGATION-TIMING]] and is now considered obsolete. The use of names from the <a data-cite="NAVIGATION-TIMING#performancetiming">PerformanceTiming</a> interface is supported to remain backwards compatible, but there are no plans to extend this functionality to names in the <a data-cite="NAVIGATION-TIMING-2#dom-performancenavigationtiming">PerformanceNavigationTiming</a> interface defined in [[NAVIGATION-TIMING-2]] (or other interfaces) in the future.
</p>
</section>
</section>
<section id="recommended-mark-names">
<h2>Recommended mark names</h2>
<p>Developers are encouraged to use the following recommended mark names to
mark common timings. The <a>user agent</a> does not validate that the usage of
these names is appropriate or consistent with its description.</p>
<p class="note">Adding such recommended mark names can help performance
tools tailor guidance to a site. These mark names can also help real user
monitoring providers and user agents collect web developer signals regarding
their application's performance at scale, and surface this information to
developers without requiring any site-specific work.</p>
<dl>
<dt>"<dfn class="export">mark_fully_loaded</dfn>"</dt>
<dd>The time when the page is considered fully loaded as marked by the
developer in their application.
<div class="note">
<p>In this example, the page asynchonously initializes a chat widget, a
searchbox, and a newsfeed upon loading. When finished, the
"<a>mark_fully_loaded</a>" mark name enables lab tools and analytics
providers to automatically show the timing.
</p>
<pre class="example">
window.addEventListener("load", (event) => {
Promise.all([
loadChatWidget(),
initializeSearchAutocomplete(),
initializeNewsfeed()]).then(() => {
performance.mark('mark_fully_loaded');
});
});
</pre>
</div>
</dd>
<dt>"<dfn class="export">mark_fully_visible</dfn>"</dt>
<dd>The time when the page is considered fully visible to an end-user
as marked by the developer in their application.</dd>
<dt>"<dfn class="export">mark_interactive</dfn>"</dt>
<dd>The time when the page is considered interactive to an end-user as
marked by the developer in their application.</dd>
<dt>"<dfn class="export">mark_feature_usage</dfn>"</dt>
<dd>Mark the usage of a feature which may impact performance so that
tooling and analytics can take it into account. The <a data-link-for="PerformanceMark">detail</a>
metadata can contain any useful information about the feature, including:
<dl>
<dt><dfn class="export">feature</dfn></dt>
<dd>The name of the feature used.</dd>
<dt><dfn class="export">framework</dfn></dt>
<dd>If applicable, the underlying framework the feature is intended
for, such as a JavaScript framework, content management system, or
e-commerce platform.</dd>
</dl>
<div class="note">
<p>In this example, the ImageOptimizationComponent for FancyJavaScriptFramework
is used to size images for optimal performance. The code notes
this feature's usage so that lab tools and analytics can measure
whether it helped improve performance.
</p>
<pre class="example">
performance.mark('mark_feature_usage', {
'detail': {
'feature': 'ImageOptimizationComponent',
'framework': 'FancyJavaScriptFramework'
}
})
</pre>
</div>
</dd>
</dl>
</section>
<section id="privacy-security" class="informative">
<h2>Privacy and Security</h2>
<p>The interfaces defined in this specification expose potentially
sensitive timing information on specific JavaScript activity of a page.
Please refer to [[HR-TIME-2]] for privacy and security considerations of
exposing high-resolution timing information.</p>
<p>Because the web platform has been designed with the invariant that any
script included on a page has the same access as any other script included
on the same page, regardless of the origin of either scripts, the
interfaces defined by this specification do not place any restrictions on
recording or retrieval of recorded timing information - i.e. a user timing
mark or measure recorded by any script included on the page can be read by
any other script running on the same page, regardless of origin.</p>
</section>
<section class="appendix">
<h2>Acknowledgments</h2>
<p>Thanks to
James Simonsen,
Jason Weber,
Nic Jansma,
Philippe Le Hegaret,
Karen Anderson,
Steve Souders,
Sigbjorn Vik,
Todd Reifsteck, and
Tony Gentilcore
for their contributions to this work.</p>
</section>
</body>
</html>