This specifications defines an interface to help web developers measure the performance of their applications by giving them access to high precision timestamps and enable them to do comparisons between them.
- Read the latest draft: https://w3c.github.io/user-timing/
- Discuss on public-webperf
See also Web performance README
User Timing enables developers to create a PerformanceMark, which contains a
provided string in name, with a high resolution timestamp (see
hr-time in its startTime, and optionally
some additional metadata in its detail.
A developer can create such an object via performance.mark() and can query
existing entries via performance.getEntriesByType('mark') (or other getters;
see performance-timeline or via
the PerformanceObserver.
The following examples illustrate usage of performance.mark() with various
parameters:
performance.mark('mark1'): Creates aPerformanceMarkwhose name is 'mark1' and whosestartTimeis the current high resolution time.performance.mark('mark2', {startTime: 5.4, detail: det}): Creates aPerformanceMarkwhose name is 'mark2', whosestartTimeis 5.4, and whosedetailis the objectdet.
Every time performance.mark() is invoked, a new PerformanceMark entry needs
to be stored by the browser so that it can be later queried by the developer.
The performance.clearMarks() method enables developers to clear some of the
memory used by such calls. In particular:
performance.clearMarks(): Clears all marks from theWindoworWorkerfrom which the method is invoked.performance.clearMarks('mark1'): Clears all marks fromWindoworWorkerfrom which the method is invoked, whose name is 'mark1'.
User Timing also enables developers to create a PerformanceMeasure, which is an
object that represents some time measurement between two points in time, and each
point in time may be represented by a PerformanceMark. A PerformanceMeasure
has an associated name, a high resolution timestamps corresponding to the initial
point in time in startTime, the delta between the end-time and the startTime in
duration, and optionally some additional metadata in its detail.
A developer can create a PerformanceMeasure entry via performance.measure() and
it may query existing entries via performance.getEntriesByType('measure') or via
PerformanceObserver (i.e. in the same way as for PerformanceMark).
The following examples illustrate usage of performance.measure() with various
parameters:
performance.measure('measure1'): Creates aPerformanceMeasurewhosenameis 'measure1', whosestartTimeis 0, and whosedurationis the current high resolution time.performance.measure('measure2', 'requestStart'): Creates aPerformanceMeasurewhose name is 'measure2', whosestartTimeis equal toperformance.timing.requestStart - performance.timing.navigationStart(see the PerformanceTiming interface for all the strings that are treated as special values inpeformance.measure()calls), and whose end-time is the current high resolution timestamp ---durationwill be the delta between the end-time andstartTime.performance.measure('measure2', 'myMark'): Creates aPerformanceMeasurewhere name is 'measure2', wherestartTimeis the timestamp from thePerformanceMarkwhosenameis'myMark', and where end-time is the current high resolution timestamp. If there are no marks with such aname, an error is thrown. If there are multiple marks with such aname, the latest one is used.performance.measure('measure3', 'startMark', 'endMark'): Creates aPerformanceMeasurewhosenameis 'measure3', whosestartTimeis thestartTimeof the latestPerformanceMarkwithname'startMark', and whose end-time is thestartTimeof the latestPerformanceMarkwithname'endMark'.performance.measure('measure4', 'startMark', 'domInteractive'): Creates aPerformanceMeasurewhosenameis 'measure4',startTimeis as in the above example, and end-time isperformance.timing.domInteractive - performance.timing.navigationStart.performance.measure('measure5', {start: 6.0, detail: det}): Creates aPerformanceMeasurewhosenameis 'measure5',startTimeis 6.0, end-time is the current high resolution timestamp, anddetailis the objectdet.performance.measure('measure6', {start: 'mark1', end: 'mark2'}): Creates aPerformanceMeasurewhosenameis 'measure6',startTimeis thestartTimeof thePerformanceMarkwithnameequal to 'mark1', and end-time is thestartTimeof thePerformanceMarkwithnameequal to 'mark2'.performance.measure('measure7', {end: 10.5, duration: 'mark1'): Creates aPerformanceMeasurewherenameis 'measure7',durationis thestartTimeof thePerformanceMarkwithnameequal to 'mark1', andstartTimeis equal to10.5 - duration(since end-time is 10.5).performance.measure('measure8', {start: 20.2, duration: 2, detail: det}: Creates aPerformanceMeasurewithnameset to 'measure8',startTimeset to 20.2,durationset to 2, anddetailset to the objectdet.
The following examples would throw errors and hence illustrate incorrect usage of
peformance.measure:
performance.measure('m', {start: 'mark1'}, 'mark2'): If the second parameter is a dictionary, then the third parameter must not be provided.performance.measure('m', {duration: 2.0}): In the dictionary, one ofstartorendmust be provided.performance.measure('m', {start: 1, end: 4, duration: 3}): In the dictionary, not all ofstart,end, anddurationshould be provided.
This is the analogue to performance.clearMarks() for PerformanceMeasure cleanup:
performance.clearMeasures()clears allPerformanceMeasureobjects.performance.clearMeasures('measure1')clearsPerformanceMeasureobjects whosenameis 'measure1'.
A developer can obtain a high resolution timestamp directly via performance.now(), as
defined in hr-time. However, User Timing enables
tracking timestamps that may happen in very different parts of the page by enabling the
developer to use names to identify these timestamps. Using User Timing instead of variables
containing performance.now() enables the data to be surfaced automatically by analytics
providers that have User Timing support as well as in the developer tooling of browsers that
support exposing these timings. This kind of automatic surfacing is not possible directly via
HR-Time.
For instance, the following could be used to track the time it takes for a user from the time a cart is created to the time that the user completes their order, assuming a Single-Page-App architecture:
// Called when the user first clicks the "Add to cart" button.
function onBeginCart() {
const initialDetail = // Compute some initial metadata about the user.
performance.mark('beginCart');
}
// Called after the user clicks on "Complete transaction" button in checkout.
function onCompleteTransaction() {
const finalDetail = // Compute some final metadata about the user and the transaction.
performance.measure('transaction', {start: 'beginCart', detail: finalDetail});
}While developers could calculate those time measurements using performance.now(), using User
Timing enables both better ergonomics and standardized collection of the results. The latter
enables Analytics providers and developer tools to collect and report site-specific measurements,
without requiring any knowledge of the site or its conventions.