docs.rodeo

MDN Web Docs mirror

Performance data

{{DefaultAPISidebar("Performance API")}} 

The Performance API measures and exposes performance data that can be collected as performance metrics for your web application. It provides methods to observe aspects of application performance. It doesn’t provide performance data analysis, or visualizations. However, the Performance API is integrated well with developer tools in browsers and its data is often sent to analytics end points and libraries to record performance metrics which help you to evaluate the data to find performance bottlenecks affecting your users.

This page provides an overview about what sorts of Performance API data exists, how it is collected, and how it can be accessed.

Collecting data

Most of the metrics exposed by the Performance API are automatically collected by the browser, and you don’t have to tell it to collect them: you just have to retrieve them.

For some metrics you do have to tell the browser what to measure:

Performance data structure

With the Performance API you can collect performance data in both {{domxref("Window.performance", "Window")}}  and {{domxref("WorkerGlobalScope.performance", "Worker")}}  global contexts. If you are collecting performance metrics for multiple contexts, take a look at {{domxref("performance.timeOrigin")}}  to synchronize time origins between contexts.

Within these contexts, individual performance data is represented by performance entries.

Performance entries

A single recorded performance data point is called a performance entry and is represented by an instance of the {{domxref("PerformanceEntry")}}  interface.

The Performance API records various different types of performance data, and the PerformanceEntry has an {{domxref("PerformanceEntry.entryType", "entryType")}}  property which is a string describing the type of this performance entry:

Performance entry subclasses

Particular entry types typically include extra type-specific data: for example, the "resource" type captures the time at which DNS lookup started and ended. So entries are represented by subclasses that extend the basic PerformanceEntry interface. For example, a "resource" entry is represented by an instance of {{domxref("PerformanceResourceTiming")}} , which inherits from PerformanceEntry, and which adds properties to record DNS lookup timestamps.

The subclasses of PerformanceEntry also define the semantics of the properties belonging to PerformanceEntry itself: for example, PerformanceEntry has a {{domxref("PerformanceEntry.name", "name")}}  property whose meaning depends on the subclass.

The following interfaces inherit from PerformanceEntry:

Accessing data

You can access performance entries in one of two ways. The preferred way is to use the {{domxref("PerformanceObserver")}}  interface, which is constructed with a callback function to be called when particular performance entries are recorded. You then call its {{domxref("PerformanceObserver.observe", "observe")}}  method, passing in the types to observe and using the buffered option to retrieve entries that occurred before observation.

function logEventDuration(entries) {
  const events = entries.getEntriesByType("event");
  for (const event of events) {
    console.log(
      `Event handler took: ${
        event.processingEnd - event.processingStart
      } milliseconds`,
    );
  }
}

const observer = new PerformanceObserver(logEventDuration);
observer.observe({ type: "event", buffered: true });

Alternatively, you can use the {{domxref("Performance.getEntries()")}} , {{domxref("Performance.getEntriesByName()")}} , and {{domxref("Performance.getEntriesByType()")}}  methods to retrieve all performance entries for a page, or entries matching the given name or type.

const events = performance.getEntriesByType("event");

for (const event of events) {
  console.log(
    `Event handler took: ${
      event.processingEnd - event.processingStart
    } milliseconds`,
  );
}

The PerformanceObserver option is preferred because:

Managing buffer sizes

There is a buffer limit for performance entries for each global object. It ensures that the browser doesn’t consume indefinite memory when holding performance data. Especially when your website or application fetches a lot of resources (e.g. when using polling), you might need to look into the limits for the buffers:

{{domxref("PerformanceEntry.entryType", "entryType")}}  identifier Interface Maximum number of buffer entries
"mark" {{domxref("PerformanceMark")}}  Infinite
"measure" {{domxref("PerformanceMeasure")}}  Infinite
"navigation" {{domxref("PerformanceNavigationTiming")}}  Infinite
"resource" {{domxref("PerformanceResourceTiming")}}  250 (adjustable, see below)
"longtask" {{domxref("PerformanceLongTaskTiming")}}  200
"paint" {{domxref("PerformancePaintTiming")}}  2 (there won’t be more)
"element" {{domxref("PerformanceElementTiming")}}  150
"event" {{domxref("PerformanceEventTiming")}}  150
"first-input" {{domxref("PerformanceEventTiming")}}  1 (there won’t be more)
"layout-shift" {{domxref("LayoutShift")}}  150
"largest-contentful-paint" {{domxref("LargestContentfulPaint")}}  150
"visibility-state" {{domxref("VisibilityStateEntry")}}  50

Table 1. Buffer sizes (source).

For "resource" entry types, see Managing resource buffer sizes for how to set a different buffer size.

For "first-input" and "paint", the limitation is inherent in the metric’s definition. There won’t be more entries than one (or two).

The performance observer callback contains an optional droppedEntriesCount parameter that tells you how many entries were lost because the buffer storage was full.

function perfObserver(list, observer, droppedEntriesCount) {
  list.getEntries().forEach((entry) => {
    // do something with the entries
  });
  if (droppedEntriesCount > 0) {
    console.warn(
      `${droppedEntriesCount} entries were dropped because the buffer was full.`,
    );
  }
}
const observer = new PerformanceObserver(perfObserver);
observer.observe({ type: "resource", buffered: true });

Another useful method is {{domxref("PerformanceObserver.takeRecords()")}}  which returns the current list of performance entries stored in the performance observer while also emptying it out.

JSON data

All performance entries provide a toJSON() {{Glossary("Serialization","serializer")}}  which returns a {{jsxref("JSON")}}  representation of the entry. This can be useful if you want to collect all of the available data and store it somewhere.

const observer = new PerformanceObserver((list) => {
  list.getEntries().forEach((entry) => {
    console.log(entry.toJSON());
  });
});

observer.observe({ type: "event", buffered: true });

This would log a JSON object like so:

{
  "name": "dragover",
  "entryType": "event",
  "startTime": 67090751.599999905,
  "duration": 128,
  "processingStart": 67090751.70000005,
  "processingEnd": 67090751.900000095,
  "cancelable": true
}

To get a string representation of the entry, you can use JSON.stringify(entry) with any PerformanceEntry object directly; it will call the entry’s toJSON() method automatically.

See also

In this article

View on MDN