ホームページ >運用・保守 >安全性 >パフォーマンスを使用してフロントエンドのパフォーマンスを監視する方法

パフォーマンスを使用してフロントエンドのパフォーマンスを監視する方法

WBOY
WBOY転載
2023-06-03 09:02:321151ブラウズ

Performance.now

Performance はフロントエンドのパフォーマンス監視に不可欠な API です。多くの値が含まれるため、ページが完全に読み込まれてから使用することをお勧めします。ページが完全にロードされる前に完全にロードする必要があります。後で取得できます。最も簡単な方法は、window.onload イベントでさまざまなデータを読み取ることです。

performance.now() メソッドは、ミリ秒単位の正確な DOMHighResTimeStamp を返します。

MDN によると:

このタイムスタンプは実際にはそれほど正確ではありません。 Spectre のようなセキュリティ脅威を軽減するために、さまざまなブラウザがこのタイプの値をさまざまな程度に四捨五入しています。 (Firefox は Firefox 59 以降、2 ミリ秒の精度に丸めます) 一部のブラウザーでは、この値がわずかにランダム化される場合もあります。この値の精度は、将来のバージョンで再び改善される可能性があります。ブラウザ開発者は、これらのタイミング攻撃とそれをより適切に軽減する方法をまだ調査中です。

なぜなら、関数の実行時間を計算するには、以下に示すように、関数の実行の前後で Performance.now() の値を 2 回比較するだけだからです。

##ここで、Firefox と Chrome で表示される結果が完全に異なることがわかります。これは、Firefox のバージョン 60 以降、パフォーマンス API の精度が 2ms に低下するためです。 パフォーマンスを使用してフロントエンドのパフォーマンスを監視する方法

Performance API にはタイムスタンプを返す機能だけでなく、必要に応じて MDN にアクセスして関連ドキュメントをクエリできる実用的なメソッドも多数備えています。

ただし、このユースケースでは、単一関数のパフォーマンスを計算するだけなので、タイムスタンプで十分です。

performance.now() は Date.now と同じですか?

「Date.now でもそれができるのでは?##」と思われるかもしれません。 # はい、できますが、欠点もあります。

Date.now は、Unix エポック (1970-01-01T00:00:00Z) からの経過時間 (ミリ秒単位) を返し、システム クロックに依存します。これは、精度が十分ではないことを意味するだけでなく、常に増分であるとは限りません。 WebKit エンジニアの Tony Gentilcore 氏は次のように説明しています。

システム時刻を日付として使用することは、最良の選択ではない可能性があり、ユーザーの監視にも適していません。ほとんどのシステムは、時刻を定期的に同期するデーモンを実行します。通常、クロックは 15 ~ 20 分ごとに数ミリ秒調整されます。その割合では、10 秒間隔の約 1% が不正確になります。

Performance.mark と Performance.measure

Performance.now 関数に加えて、パフォーマンスのさまざまな部分の時間を測定できる関数がいくつかあります。コードを作成し、Webpagetest などのパフォーマンス テスト ツールでカスタム メトリクスとして使用します。

Performance.mark

まず MDN のマーク メソッドの定義を見てみましょう:

マーク() メソッドは、指定された名前でブラウザのパフォーマンス エントリ バッファにタイムスタンプを作成します。

  • この段落は 3 つのキーワードに分解できます。最初のタイムスタンプ。ここでのタイムスタンプは高精度タイムスタンプ (1000 分の 1 ミリ秒) を指し、その後にパフォーマンス エントリ バッファーが続きます。

  • パフォーマンスエントリバッファとは、パフォーマンスインスタンスオブジェクトが格納される領域を指し、初期値は空です。

最後は指定された名前です。これは、生成された各タイムスタンプが対応する名前を持つことを意味します。

したがって、この文は、ブラウザのパフォーマンス エントリ バッファ内の名前に基づいて高精度のタイムスタンプを生成すると理解できます。これは、多くの人が **「管理」** と呼ぶものです。

Performance.now と同様に、この関数の精度スコアは最大 5µs です。

const t0 = performance.now(); for (let i = 0; i <p> とマークされたパフォーマンス エントリには、次の属性値があります: </p><p></p><p>entryType - "mark".</p>
  • name に設定されます。 - マークの作成時に指定された "name"

  • #startTime に設定します。 - mark() メソッドが呼び出されたときのタイムスタンプに設定します。

  • duration - 「0」に設定します (マーカーには継続時間がありません)。

  • Performance.measure

MDN のメジャーの定義も見てみましょう: この定義は、上記のマークの定義に似ていますが、中心的な違いは、指定された 2 つのマークの間の文にあります。したがって、measure は 2 つのマーク ポイント間のタイムスタンプを指定します。マークが「点」だと理解すれば、メジャーは「つながり」と理解できます。

performance.mark('name');

2 つのマーク間の期間を計算し、DOMHighResTimeStamp を作成してリソース キャッシュ データに保存します。このデータは、performance.getEntries() などの関連インターフェイスを通じて取得できます。

entryType は文字列メジャーです

  • name は作成時に設定された値です

  • startTime はメジャーが呼び出される時間

  • #duration は 2 つのマーク間の継続時間です

  • #ナビゲーションからの測定

    performance.measure(name, startMark, endMark);
ナビゲーションはタグから始まります

performance.measure('measure name');

タグからタグへ

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

リソース パフォーマンス データ

#パフォーマンス エントリ バッファからデータを取得します

#

在上面的函数中,总是提到结果存储在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="パフォーマンスを使用してフロントエンドのパフォーマンスを監視する方法"></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 中运行上述函数,结果:

パフォーマンスを使用してフロントエンドのパフォーマンスを監視する方法

看起来forEach慢多了,对吧?

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

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

パフォーマンスを使用してフロントエンドのパフォーマンスを監視する方法

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

在多个浏览器中测试

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

パフォーマンスを使用してフロントエンドのパフォーマンスを監視する方法

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

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

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

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

限制的 CPU

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

ブラウザには CPU パフォーマンスを制限する機能があり、実際の状況に合わせて設定できます。

以上がパフォーマンスを使用してフロントエンドのパフォーマンスを監視する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。