Home  >  Article  >  Operation and Maintenance  >  How to use Performance to monitor front-end performance

How to use Performance to monitor front-end performance

WBOY
WBOYforward
2023-06-03 09:02:321110browse

Performance.now

Performance is an API that is indispensable for front-end performance monitoring. It is best to use it after the page is fully loaded, because many values ​​​​must be fully loaded before the page You can get it later. The simplest way is to read various data in the window.onload event.

The performance.now() method returns a DOMHighResTimeStamp accurate to milliseconds.

According to MDN:

This timestamp is not actually highly accurate. In order to reduce security threats like Specter, various browsers round off the value of this type to varying degrees. (Firefox rounds to 2 millisecond precision starting with Firefox 59) Some browsers may also slightly randomize this value. The accuracy of this value may improve again in future versions; browser developers are still investigating these timing attacks and how to better mitigate them.

Because, to calculate the execution time of a function, just compare the two performance.now() values ​​before and after the function execution, as shown below:

const t0 = performance.now(); for (let i = 0; i <p><img src="https://img.php.cn/upload/article/000/887/227/168575415495196.png" alt="How to use Performance to monitor front-end performance"></p><p>Here you can observe that the results presented by Firefox and Chrome are completely different. This is because starting with version 60, Firefox reduces the precision of the performance API to 2ms. </p><p>Performance API should not only have the function of returning timestamps, but also has many practical methods. You can go to MDN to query related documents as needed. </p><p>However, for our use case, we only want to calculate the performance of a single function, so the timestamp will be enough. </p><p><strong>Is performance.now() the same as Date.now?</strong></p><p>You might be thinking, hey, I can do that with Date.now too?</p> <p> Yes, you can, but there are drawbacks. </p><p>Date.now returns the elapsed time (in milliseconds) since the Unix epoch (1970-01-01T00:00:00Z) and depends on the system clock. Not only does this mean it's not precise enough, but it's not always incremental. Here, WebKit engineer Tony Gentilcore explains: </p><p>Using the system time as the date may not be the best choice, nor is it suitable for user monitoring. Most systems run a daemon that synchronizes the time periodically. Typically the clock is adjusted by a few milliseconds every 15 to 20 minutes. At that rate, about 1% of 10 second intervals will be inaccurate. </p><p><strong>Performance.mark and Performance.measure</strong></p><p>In addition to the Performance.now function, there are some functions that allow us to measure the time of different parts of the code and use them as Custom metrics in performance testing tools like Webpagetest. </p><p><strong>Performance.mark</strong></p><p>Let’s first take a look at the definition of the mark method in MDN:</p>
  • The mark() method creates a timestamp in the browser's performance entry buffer with the given name.

This paragraph can be broken down into three keywords. First timestamp, timestamp here refers to high-precision timestamp (one thousandth of a millisecond), followed by performance entry buffer.

Performance entry buffer refers to the area where performance instance objects are stored, and the initial value is empty.

The last is the given name, which means that each generated timestamp has a corresponding name.

So this sentence can be understood as generating a high-precision timestamp based on the name in the browser's performance entry buffer. This is what many people call **"management"**.

Just like Performance.now, this function has a precision score of up to 5µs. Performance entries marked

performance.mark('name');

will have the following attribute values:

  • entryType - set to "mark".

  • name - Set to the "name"

  • #startTime given when the mark was created - Set to the timestamp when the mark() method was called.

  • duration - Set to "0" (marker has no duration).

Performance.measure

Let’s also take a look at the definition of measure on MDN:

This definition is somewhat similar to the definition of mark above. The core difference lies in the sentence between two specified marks. So measure specifies the timestamp between two mark points. If mark can be understood as "dot", measure can be understood as "connection".

performance.measure(name, startMark, endMark);

Calculate the duration between two marks, create a DOMHighResTimeStamp and save it in the resource cache data, which can be obtained through related interfaces such as performance.getEntries().

  • entryType is the string measure

  • name is the value set when creating

  • startTime is The time when measure is called

  • duration is the duration between two marks

Measuring from navigation

performance.measure('measure name');

Navigation starts to tag

performance.measure('measure name', undefined, 'mark-2');

From tag to tag

performance.measure('measure name', 'mark-1', 'mark-2');

Resource performance data

Get data from performance entry buffer

在上面的函数中,总是提到结果存储在performance entry buffer,但是如何访问其中的内容呢?

performance API有3个函数可以用来访问该数据:

performance.getEntries()

获取一组当前页面已经加载的资源PerformanceEntry对象。接收一个可选的参数options进行过滤,options支持的属性有name,entryType,initiatorType。

let entries = window.performance.getEntries();

performance.getEntriesByName

根据参数name,type获取一组当前页面已经加载的资源数据。资源数据中的"name"字段对应于"name"的取值,资源数据中的"entryType"字段对应于"type"的取值。

let entries = window.performance.getEntriesByName(name, type);

performance.getEntriesByType

根据参数type获取一组当前页面已经加载的资源数据。type取值对应到资源数据中的entryType字段。

var entries = window.performance.getEntriesByType(type);

结合事例:

performance.mark('mark-1'); // some code performance.mark('mark-2') performance.measure('test', 'mark-1', 'mark-2') console.log(performance.getEntriesByName('test')[0].duration);

Console.time

这个  API确实易于使用。当需要统计一段代码的执行时间时,可以使用console.time方法与console.timeEnd方法,其中console.time方法用于标记开始时间,console.timeEnd方法用于标记结束时间,并且将结束时间与开始时间之间经过的毫秒数在控制台中输出。这两个方法的使用方法如下所示。

console.time('test'); for (let i = 0; i <p><img src="https://img.php.cn/upload/article/000/887/227/168575415499236.png" alt="How to use Performance to monitor front-end performance"></p><p>输出的结果与Performance API非常相似。</p><p>console.time的优点是易于使用,因为它不需要手动计算两个时间戳之间的差。</p><p><strong>减少时间精度</strong></p><p>如果在不同的浏览器中使用上面提到的 api 测量函数,你可能会注意到结果是不同的。</p><p>这是由于浏览器试图保护用户免受时序攻击(timing attack)和指纹采集(Fingerprinting  ),如果时间戳过于准确,黑客可以使用它们来识别用户。</p><p>例如,Firefox等浏览器试图通过将精度降低到2ms(版本60)来防止这种情况发生。</p><p><strong>注意事项</strong></p><p>现在,我们已经知道了要测量JavaScript函数的速度所需方法。但是,最好还要避免一些陷阱:</p><p><strong>分而治之</strong></p><p>开发过程中,我们可能会我发现有些模块执行速度很慢,但是我们不知道具体问题出在哪里。一种解决方案是使用前面提到的这些函数来测量代码,而不是随便猜测哪一部分比较慢。</p><p>为了跟踪它,你需要在执行速度较慢的代码块周围放置console.time语句。然后测量它们不同部分的表现。如果一个比另一个慢,那就继续往下走,直到发现问题所在。</p><p><strong>注意输入值</strong></p><p>在实际应用中,给定函数的输入值可能会发生很大变化。我们无法通过仅针对任意随机值测量函数的速度来获得任何实用的有价值数据。</p><p><strong>确保使用相同的输入值运行代码。</strong></p><p><strong>多次运行该函数</strong></p><p>如果你拥有一个函数,它的功能在于遍历一个数组,在对数组的每个值执行一些计算后,返回一个包含计算结果的新数组。你想知道是forEach循环还是简单的for循环性能更好。</p><pre class="brush:php;toolbar:false">function testForEach(x) {   console.time('test-forEach');   const res = [];   x.forEach((value, index) => {     res.push(value / 1.2 * 0.1);   });    console.timeEnd('test-forEach')   return res; }  function testFor(x) {   console.time('test-for');   const res = [];   for (let i = 0; i <p>然后这样测试它们:</p><pre class="brush:php;toolbar:false">const x = new Array(100000).fill(Math.random()); testForEach(x); testFor(x);

如果在 Firefox 中运行上述函数,结果:

How to use Performance to monitor front-end performance

看起来forEach慢多了,对吧?

那如果是相同的输入,运行两次呢:

testForEach(x); testForEach(x); testFor(x); testFor(x);

How to use Performance to monitor front-end performance

在第二次调用forEach的情况下,其执行效果应该是和使用for循环相同。考虑到初始值较慢,在一些性能要求极高的项目,可能就不适合使用forEach。

在多个浏览器中测试

如果我们在Chrome中运行上述代码,结果又会不一样:

How to use Performance to monitor front-end performance

这是因为Chrome和Firefox具有不同的JavaScript引擎,它们具有不同类型的性能优化。

在本例中,Firefox 在对相同输入的forEach进行优化方面做得更好。

for在两个引擎上的性能都更好,因此在一些性能要求极高的项目就需要使用for循环。

这是为什么要在多个引擎中进行测量的一个很好的例子。只使用Chrome作为度量标准可能导致你得出结论,forEach与for相比并不那么糟糕。

限制的 CPU

在本地测试时得到的结果不代表用户在浏览器中的使用情况,因为我们开发者使用的电脑通常比大多数用户的电脑配置更好。

The browser has a feature that can limit CPU performance. We can set it to be more appropriate to the real situation.

The above is the detailed content of How to use Performance to monitor front-end performance. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete