【JavaScript】Performance APIで処理時間を計測する方法!

JavaScriptではPerformance APIを用いると、処理時間を計測することができます。

この記事では『JavaScriptで処理時間を計測する方法』について、以下の内容をサンプルコードを用いて分かりやすく説明するように心掛けています。ご参考になれば幸いです。

  • Performance APIとは
  • Performanceインターフェースとは
  • 基本的な計測方法(performance.nowを用いる)
  • performance.mark()performance.measure()を使った計測方法
    • performance.getEntries()の使い方
    • performance.getEntriesByName()の使い方
    • performance.getEntriesByType()の使い方

Performance APIとは

Performance APIは、Webブラウザが提供するAPIで、スクリプトの実行時間やWebページのロード時間など、パフォーマンスに関するさまざまなデータを取得するためのAPIです。

Performance APIを用いて、JavaScriptの処理時間を計測することで、パフォーマンスに問題のある箇所を特定することができます。

Performanceインターフェースとは

Performanceインターフェースは、処理時間を計測するための様々なメソッドを提供しています。

主なメソッドとして以下のものがあります。

  • performance.now()
    • 現在の時刻をミリ秒で取得する。
  • performance.mark()
    • 呼び出したタイミングにマークを付ける。
  • performance.measure()
    • 2つのマーク間の時間を測定する。
  • performance.getEntries()
    • すべてのパフォーマンスエントリを取得する。
  • performance.getEntriesByName()
    • 特定の名前に一致する全てのパフォーマンスエントリを取得する。
  • performance.getEntriesByType()
    • 特定のタイプに一致する全てのパフォーマンスエントリを取得する。

Performanceインターフェースは、window.performanceもしくは単にperformanceでアクセスできます。performanceと書くのが一般的です。

基本的な計測方法(performance.nowを用いる)

performance.now()を用いると、JavaScriptの処理時間を簡単に計測することができます。計測したい処理の前後にperformance.now()を呼び出し、その差分を計測します。

サンプルコードを以下に示します。

// 処理開始時刻を記録
const start = performance.now();

// 計測したい処理
for (let i = 0; i < 1000000; i++) {
  // ループ処理
}

// 処理終了時刻を記録
const end = performance.now();

// 処理開始時刻と処理終了時刻の差分(処理の計測時間)をログ出力
console.log(`処理時間: ${end - start} ミリ秒`);

// ログ出力例
// 処理時間: 2.2010000000000005 ミリ秒

上記のサンプルコードでは、処理開始時刻(start)と処理終了時刻(end)を記録し、その差分を計測しています。

performance.mark()とperformance.measure()を使った計測方法

performance.mark()performance.measure()を使った計測方法の流れを以下に示します。

  • performance.mark()で特定時点にマークを付けます。
  • マークを2つ以上作成したら、performance.measure()でマーク間の時間を測定します。
  • 計測時間を取得するために、performance.getEntries()performance.getEntriesByName()performance.getEntriesByType()のいずれかを使用します。

サンプルコードを以下に示します。以下のサンプルコードではperformance.getEntriesByName()を用いて計測時間を取得しています。

// 開始時点にマークを付ける
performance.mark('startTask');

// 計測したい処理
for (let i = 0; i < 1000000; i++) {
  // ループ処理
}

// 終了時点にマークを付ける
performance.mark('endTask');

// 2つのマーク間の時間を測定する
performance.measure('Task Duration', 'startTask', 'endTask');

// 測定結果を表示
const measures = performance.getEntriesByName('Task Duration');
console.log(`処理時間: ${measures[0].duration} ミリ秒`);

// ログ出力例
// 処理時間: 2.635799999999996 ミリ秒

上記のサンプルコードでは、処理の開始(startTask)と終了(endTask)のマークを付け、performance.measure()でマーク間の時間を測定しており、Task Durationという名前を付けています。最後にperformance.getEntriesByName('Task Duration')Task Durationという名前に一致する処理時間を計測しています。

performance.getEntries()の使い方

performance.getEntries()を用いると、すべてのパフォーマンスエントリを取得することができます。

サンプルコードを以下に示します。

function func1() {
  console.log('func1');
}
function func2() {
  console.log('func2');
}
function func3() {
  console.log('func3');
}

performance.mark('start');
func1();
performance.mark('point1');
func2();
performance.mark('point2');
func3();
performance.mark('end');

performance.measure('func1Time', 'start', 'point1');
performance.measure('func2Time', 'point1', 'point2');
performance.measure('func3Time', 'point2', 'end');
performance.measure('allTime', 'start', 'end');

// `performance.getEntries()` で全てのパフォーマンスエントリを取得し、表示する
const entries = performance.getEntries();
for (const entry of entries) {
  console.log(
    `名前: ${entry.name}, タイプ: ${entry.entryType}, 処理時間: ${entry.duration}, タイムスタンプ: ${entry.startTime}`
  );
}
// ログ出力例
// func1
// func2
// func3
// 名前: start, タイプ: mark, 処理時間: 0, タイムスタンプ: 29.3005
// 名前: func1Time, タイプ: measure, 処理時間: 8.259900000000002, タイムスタンプ: 29.3005
// 名前: allTime, タイプ: measure, 処理時間: 8.985999999999997, タイムスタンプ: 29.3005
// 名前: point1, タイプ: mark, 処理時間: 0, タイムスタンプ: 37.5604
// 名前: func2Time, タイプ: measure, 処理時間: 0.37939999999999685, タイムスタンプ: 37.5604
// 名前: point2, タイプ: mark, 処理時間: 0, タイムスタンプ: 37.9398
// 名前: func3Time, タイプ: measure, 処理時間: 0.34669999999999845, タイムスタンプ: 37.9398
// 名前: end, タイプ: mark, 処理時間: 0, タイムスタンプ: 38.2865

上記のサンプルコードでは、performance.getEntries()を使って、すべてのパフォーマンスエントリ(markmeasureの両方)を取得しています。ログ出力の際には、entryTypeを使ってエントリの種類(markまたはmeasure)も表示しています。

performance.getEntries()で取得できるエントリの順番は、performance.mark()performance.measure()を使用して記録したパフォーマンスエントリのタイムスタンプの順番になっています。なお、performance.measure()のタイムスタンプは、第二引数(開始マーク)と一致します。つまり、performance.measure('func1Time', 'start', 'point1')の場合、計測結果のタイムスタンプは'start'のマークと一致します。

performance.getEntriesByName()の使い方

performance.getEntriesByName()を用いると、特定の名前に一致する全てのパフォーマンスエントリを取得することができます。

サンプルコードを以下に示します。

function func1() {
  console.log('func1');
}
function func2() {
  console.log('func2');
}
function func3() {
  console.log('func3');
}

performance.mark('start');
func1();
performance.mark('point1');
func2();
performance.mark('point2');
func3();
performance.mark('end');

performance.measure('func1Time', 'start', 'point1');
performance.measure('func2Time', 'point1', 'point2');
performance.measure('func3Time', 'point2', 'end');
performance.measure('allTime', 'start', 'end');

// 特定のmeasureの名前でエントリを取得
const func1Entries = performance.getEntriesByName('func1Time');
const func2Entries = performance.getEntriesByName('func2Time');
const func3Entries = performance.getEntriesByName('func3Time');
const allEntries = performance.getEntriesByName('allTime');

console.log(`func1Time: ${func1Entries[0].duration}`);
console.log(`func2Time: ${func2Entries[0].duration}`);
console.log(`func3Time: ${func3Entries[0].duration}`);
console.log(`allTime: ${allEntries[0].duration}`);

// ログ出力例
// func1
// func2
// func3
// func1Time: 7.969999999999999
// func2Time: 0.3791000000000011
// func3Time: 0.3089999999999975
// allTime: 8.658099999999997

上記のサンプルコードでは、performance.getEntriesByName()を使って、特定の名前(func1Timefunc2Timeなど)に一致するパフォーマンスエントリのみを取得し、その処理時間を表示しています。

performance.getEntriesByType()の使い方

performance.getEntriesByType()を用いると、特定のタイプに一致する全てのパフォーマンスエントリを取得することができます。

サンプルコードを以下に示します。

function func1() {
  console.log('func1');
}
function func2() {
  console.log('func2');
}
function func3() {
  console.log('func3');
}

performance.mark('start');
func1();
performance.mark('point1');
func2();
performance.mark('point2');
func3();
performance.mark('end');

performance.measure('func1Time', 'start', 'point1');
performance.measure('func2Time', 'point1', 'point2');
performance.measure('func3Time', 'point2', 'end');
performance.measure('allTime', 'start', 'end');

// "measure"タイプのエントリのみを取得して表示
const measureEntries = performance.getEntriesByType('measure');
console.log('measureエントリ:');
for (const entry of measureEntries) {
  console.log(`${entry.name}: ${entry.duration}ミリ秒`);
}

// "mark"タイプのエントリのみを取得して表示
const markEntries = performance.getEntriesByType('mark');
console.log('markエントリ:');
for (const entry of markEntries) {
  console.log(`${entry.name} (タイムスタンプ: ${entry.startTime}ミリ秒)`);
}

// 実行結果例
// func1
// func2
// func3
// measureエントリ:
// func1Time: 6.902599999999996ミリ秒
// allTime: 7.645ミリ秒
// func2Time: 0.42540000000000333ミリ秒
// func3Time: 0.31700000000000017ミリ秒
// markエントリ:
// start (タイムスタンプ: 27.8274ミリ秒)
// point1 (タイムスタンプ: 34.73ミリ秒)
// point2 (タイムスタンプ: 35.1554ミリ秒)
// end (タイムスタンプ: 35.4724ミリ秒)

performance.getEntriesByType("measure")measureタイプのパフォーマンスエントリのみを取得しています。これにより、performance.measure()によって記録された処理の計測時間を取得することができます。

performance.getEntriesByType("mark")markタイプのパフォーマンスエントリのみを取得しています。これにより、performance.mark()で付けたマークの実行時間を取得することができます。

このように、measureタイプのパフォーマンスエントリでは処理の計測時間、markタイプのパフォーマンスエントリでは処理の開始時刻や終了時刻(タイムスタンプ)を取得することができます。

本記事のまとめ

この記事では『JavaScriptで処理時間を計測する方法』について、以下の内容を説明しました。

  • Performance APIとは
  • Performanceインターフェースとは
  • 基本的な計測方法(performance.nowを用いる)
  • performance.mark()performance.measure()を使った計測方法
    • performance.getEntries()の使い方
    • performance.getEntriesByName()の使い方
    • performance.getEntriesByType()の使い方

お読み頂きありがとうございました。