loading...

Performance measuring

victormagarlamov profile image Victor Magarlamov Updated on ・2 min read

Measure first and then optimize!
-- Golden rule

You can't optimize what you can't measure.
-- Another golden rule

There are many articles on how to improve performance in JavaScript applications. Of course, it’s good to know all these tricks and tips, but it’s much better to know what I will tell in this article 😇.

Three key performance features

  1. Navigation speed
  2. Resources loading speed
  3. Code execution speed

In general, web application performance depends on these characteristics — navigation, resources, and scripting. And together they are part of the Performance Timeline. Thanks to the Performance Web API, we can easily measure and read Performance Timeline metrics. Let's do it.

Navigation Timing

function getNavigationMetric () {
  const [entry] = performance.getEntriesByType("navigation");
  console.table(entry.toJSON());
}

The getEntriesByType method returns a list of the PerfomanceEntity objects, each of which is a part of the Performance Timeline. In this case, we get an object of type “navigation”. This type will be contained in the initiatorType property of the object, which we will see in the console after calling our function in the body.onload (or in the componentDidMount life cycle method in a React app).

Other interesting properties will be: responseEnd - time of the last byte received from the navigation request (startTime) and duration - equal to the difference between responseEnd and startTime, respectively.

Resource Timing

function getResourceMetric () {
  const entries = performance.getEntriesByType("resource");
  console.log(entries);
}

When we call this function in body.onload, we get PerfomanceEntity for all the resources that the page loads. If we filter these entries by initiatorType, we get metrics for images (initiatorType === “img”), scripts (initiatorType === “script”), etc.

User Timing

function getUserMetric () {
  performance.mark("do_something_start_mark");
  doSomething();
  performance.mark("do_something_end_mark");

  performance.measure("measure", "do_something_start_mark", "do_something_end_mark");

  const entries = performance.getEntriesByType("measure");
  console.log(entries);
}

In this case, we get the timeline metric from startMark to the endMark label. By the way, it’s good practice to delete the used metric using the performance.clearMeasures method.

PerfomanceObserver

Well, we have metrics, and now we can send them to the server for analysis. The best way to do this is to use the Performance Observer API.

const observer = new PerformanceObserver(list => {
  const res = list.getEntries().map(entry => ({
    name: entry.name,
    type: entry.entryType,
    start: entry.startTime,
    duration: entry.duration,
  }));

  sendMetrics(res);
});

observer.observe({entryTypes: ['resource', 'navigation', 'measure']});

More about the Perfomance Timeline API

Discussion

markdown guide
 

The best way to do this is to use the Performance Observer API.

By accident i was writing almost exactly the same code today, but didnt see Observer API in MDN, why is it the best way to do it?

 

Because WebAPI's observers do they work in own thread, asynchronously.

 

Ouh, i just did setTimeout 100 and it worked out cool ;)

 

Nice Victor thanks!

 const [entry] = performance.getEntriesByType("navigation");

Is performance a library?

 

Yes, I forgot to say it! Sorry! Performance is a property of the window object. developer.mozilla.org/en-US/docs/W...