ユーザータイミングAPI

この記事は、 HTML5Rocksの寄稿者 Alex Daniloによって2014年1月21日に書かれました。 これがHabréでの最初の翻訳であることに注意してください。 すべての問題と欠点については、個人的に私に書いてみてください、私はすぐにそれを修正します。 英語のオリジナル



高いWebアプリケーションパフォーマンスは、エンドユーザーにとって重要です。 Webアプリケーションがますます複雑になるにつれて、パフォーマンス管理を理解することはプログラマにとって魅力的なスキルです。 過去数年にわたって、ブラウザに多くの新しいAPIが登場し、ネットワークパフォーマンス、ダウンロード時間などを監視できるようになりました。 ただし、どれもアプリケーションを正確に「遅くする」ものを十分に柔軟かつ詳細に定義することはできません。 このために、 ユーザーのタイミングAPIがあります 。これは、アプリケーションに時間と時間を決定できるメカニズムを提供します。





測定できないものを最適化することは不可能です



低速なWebアプリケーションを高速化するために最初に必要なことは、完了するのに最も時間がかかる場所を特定することです。 JavaScriptコードの個々のセクションの実行時間を測定することは、ホットスポットを識別するための理想的な方法です。 これは、パフォーマンスを改善する方法を見つけるための最初のステップです。 幸いなことに、 ユーザータイミングAPIは、コード内のさまざまな場所でAPIを呼び出して、最適化に役立つ詳細な時間データを取得できるソリューションを提供します。



今すぐ高解像度の時間と方法()



時間測定の基本的な部分は精度です。 以前は、1ミリ秒の測定誤差で管理していましたが、各フレームが16ミリ秒で描画されるジャンクフリーサイトが現れました。 したがって、ミリ秒誤差を適切に分析するには十分ではありません。 しかし現在、 高解像度時間があります。これは、最新のブラウザに組み込まれた新しいタイプの同期です。 高解像度時間は、マイクロ秒単位の正確な浮動小数点タイムスタンプを提供します。これは、以前の何千倍も優れています。



アプリケーションの現在の時刻を取得するには、今すぐ()メソッドを呼び出す必要があります。これは、Performanceインターフェイスの拡張機能です。



var myTime = window.performance.now();
      
      





Webアプリケーションの読み込み方法に関連する一連の時点を提供するPerformanceTimingと呼ばれる別のインターフェイスがあります。 now()メソッドは、 PerformanceTimingからnavigationStartから経過した時間を返します。



タイプDOMHighResTimeStamp



以前は、現在のアプリケーションの時刻を取得するために、DOMTimeStampを返すDate.now()関数が使用されていました 。 DOMTimeStampはミリ秒の整数を返しました。 高解像度時間の精度を高めるために、DOMHighResTimeStampと呼ばれる新しいタイプが導入されました。 この型には既に浮動小数点がありますが、ミリ秒単位の時間も返します。 ただし、整数以外の値のおかげで、時間にはミリ秒の小数部が含まれ、1000分の1ミリ秒の精度が得られます。



ユーザータイミングインターフェース



現在、高精度の時間があるため、ユーザータイミングを使用して時間情報を取得できます。



ユーザータイミングインターフェイスは、アプリケーションのさまざまな場所で呼び出して弱点を特定できる関数を提供します。



マーク()を使用する



この方法は、時間分析ツールの主要な方法です。 mark()は何をしますか? この方法は、将来の使用のために時間を節約します。 しかし、その中で最も役立つのは、マークに名前を付けることができることです。 この場合、APIは名前と時間の関係を別の要素として保存します。



さまざまな場所でmark()を使用すると、呼び出し間でどれだけの時間が経過したかを判断できます。



仕様では、「mark_fully_loaded」、「mark_fully_visible」、「mark_above_the_fold」など、かなり理解しやすい標準ラベル名が提供されていました。



たとえば、アプリケーションが完全にロードされたときにマークを付けることができます。



 window.performance.mark('mark_fully_loaded');
      
      





アプリケーション全体に名前付きラベルを設定することで、膨大な量のデータを収集し、いつでもアプリケーションで時間と何を費やすべきかを把握するために分析できます。



測定と測定()メソッド



タイムスタンプを設定したら、それらの間の時間を計算する必要があります。 このためには、measure()メソッドが必要です。 マーク間で発生した時間を決定します。 また、ユーザーマークとパフォーマンスタイミングインターフェースにリストされている標準的なマークの1つとの間の時間も決定できます。 たとえば、DOMが読み込まれてからアプリケーションが完全に読み込まれるまでの時間を計算するには、次のコードを使用します。



 window.performance.measure('measure_load_from_dom', 'domComplete', 'mark_fully_loaded');
      
      





注:この例では、 パフォーマンスタイミングインターフェイスから予約名「domComplete」を渡します。



measure()メソッドが呼び出されると、ラベルに関係なく結果が保存されるため、後でこの値を取得できます。 アプリケーションの実行時に時間データを個別に保存することにより、応答性と効率性が維持され、アプリケーションが何らかの作業を行った後、分析のためにデータをアップロードできます。



clearMarks()によるマークのリセット



保存された多数のマークを取り除くと便利な場合があります。 たとえば、コマンドラインからアプリケーションを実行できるため、開始する前に蓄積されたすべてのマークをリセットするのが論理的です。



clearMarks()を呼び出して、設定マークを取り除くのは簡単です。



したがって、次のコード例では既存のマークをすべてクリアするため、必要に応じて再度設定できます。



 window.performance.clearMarks();
      
      





もちろん、すべてのマークをクリアしたくない状況もあります。 特定のものを削除したい場合は、削除するマークの名前を渡すだけです。 たとえば、次のように:



 window.peformance.clearMarks('mark_fully_loaded');
      
      





このコードは、上記で保存されたマークを取り除きます。 しかし、他のすべてのマークは消えません。



行った測定値を削除することもできます。 これには適切なclearMeasures()メソッドがあります。 clearMarks()と同じように機能します。 例:



 window.performance.clearMeasures('measure_load_from_dom');
      
      





上記の例で保存したディメンションを削除します。 すべてのディメンションを削除するには、clearMarks()のように、引数なしで同じメソッドを呼び出す必要があります。



時間データの保存



マークを設定して時間を測定することはすべて良いことですが、ある時点で、分析のためにこのデータを取得する必要があります。 また、非常にシンプルで、 PerformanceTimelineインターフェースを使用するだけです。



たとえば、getEntriesByType()メソッドを使用すると、すべてのマークまたはすべての測定値をリストの形式で取得できるため、そのマークを通過してデータを処理できます。 便利なのは、リストが時系列で返されることです。アプリケーションでマークが呼び出されると、マークを追跡できます。



次のコード:



 var items = window.performance.getEntriesByType('mark');
      
      





このコードは、アプリケーションでマークされたすべてのマークを返します。



 var items = window.performance.getEntriesByType('measure');
      
      





行われたすべての測定値を返します。



割り当てた名前でエントリのリストを取得することもできます。



 var items = window.performance.getEntriesByName('mark_fully_loaded');
      
      





startTimeプロパティにタイムスタンプ「mark_fully_loaded」を含む1つの要素を含むリストを返します。



XHRリクエストの時間を計算する例



User Timing APIの全体像がわかったので、XHRリクエストのすべてがアプリケーションで実行されている時間を判断します。



まず、すべてのsend()リクエストを変更してそれらにマークを設定する必要があります。また、他のマークが設定されるコールバック関数も変更する必要があります。 また、それらの間の時間を測定して、リクエストの期間を決定します。



通常、単純なXHRリクエストは次のようになります。



 var myReq = new XMLHttpRequest(); myReq.open('GET', url, true); myReq.onload = function(e) { do_something(e.responseText); } myReq.send();
      
      





たとえば、クエリの数を監視し、各クエリの測定値を保存する際に使用するグローバルカウンターを追加します。 このコードは次のようになります。



 var reqCount = 0; var myReq = new XMLHttpRequest(); myReq.open('GET', url, true); myReq.onload = function(e) { window.performance.mark('mark_end_xhr'); reqCnt++; window.performance.measure('measure_xhr_' + reqCnt, 'mark_start_xhr', 'mark_end_xhr'); do_something(e.responseText); } window.performance.mark('mark_start_xhr'); myReq.send();
      
      





このコードは、送信するXHRリクエストごとに一意の名前を持つディメンションを生成します。 すべてのリクエストは順番に実行されると想定していますが、パラレルリクエストの場合、コードを少し変更する必要があります。 したがって、これを読者のための家庭演習として残しましょう。



Webアプリケーションが多くの要求を行った後、次のコードを使用してコンソールにデータを出力できます。



 var items = window.performance.getEntriesByType('measure'); for (var i = 0; i < items.length(); ++i) { var req = items[i]; console.log('XHR ' + req.name + ' took ' + req.duration + 'ms'); }
      
      





おわりに



User Timing APIは、アプリケーションのさまざまな部分ですぐに使用できる多くの優れたツールを提供します。 弱点の数を減らすことは、アプリケーション全体にAPI呼び出しを配置すること、および受信したデータの事後分析によって簡単に達成できます。 しかし、ブラウザがこのAPIをサポートしていない場合はどうでしょうか? 問題ありません。APIを非常によくエミュレートしシステムをロードしません 。 それで、あなたは何を待っていますか? アプリケーションを高速化するために、今すぐアプリケーションでユーザータイミングAPIを試してください。ユーザーに感謝します。



All Articles