JavaScript | Web API:パフォーマンス・セキュリティ - 計測(time / mark)

JavaScript JavaScript
スポンサーリンク

「計測」は“なんとなく遅い”を数字に変えるための技術

パフォーマンスの話で一番大事なのは、
「速い/遅い」を 感覚ではなく数字で話せるようになること です。

そのために使うのが、
console.time / console.timeEnd
performance.mark / performance.measure です。

どちらも「処理にどれくらい時間がかかったか」を測る道具ですが、
用途とスケールが少し違います。

ここでは、初心者向けに
「まずこれだけ押さえておけばいい」という形で整理していきます。


console.time / console.timeEnd で“とりあえず測る”

基本の使い方とイメージ

console.time は「ストップウォッチをスタートする」
console.timeEnd は「ストップウォッチを止めて結果を表示する」
そんなイメージです。

ラベル(名前)をつけて使います。

console.time("heavyTask");

function heavyTask() {
  const arr = [];
  for (let i = 0; i < 200000; i++) {
    arr.push(Math.random());
  }
  arr.sort();
}

heavyTask();

console.timeEnd("heavyTask");
JavaScript

ブラウザのコンソールには、例えばこんな感じで出ます。

heavyTask: 47.32 ms

これだけで、

「この処理はだいたい 50ms くらいかかるのか」
「100ms 超えてるからちょっと重いな」

といった感覚が、数字と一緒に掴めます。

よくあるミスと注意点

一番多いミスは、ラベル名を揃えないことです。

console.time("task");
// ...
console.timeEnd("taks"); // スペルミス → 結果が出ない
JavaScript

console.timeconsole.timeEnd のラベルは
完全に同じ文字列 である必要があります。

もうひとつの注意点は、
console.time はあくまで「開発中の計測用」ということです。

本番コードに大量に残しておくと、
ログがうるさくなったり、
場合によってはパフォーマンスに影響することもあります。

「開発中に使って、不要になったら消す」
くらいの感覚で使うのがちょうどいいです。


performance.mark / performance.measure で“区間に名前をつけて測る”

「ここからここまで」をラベル付きで計測する

performance.mark は「ここに印をつける」
performance.measure は「印と印の間の時間を測る」
というイメージです。

少しだけ丁寧に計測したいときに使います。

performance.mark("init-start");

// 初期化処理(例)
initUser();
initUI();
initEvents();

performance.mark("init-end");

performance.measure("init-duration", "init-start", "init-end");

const [measure] = performance.getEntriesByName("init-duration");
console.log(`初期化にかかった時間: ${measure.duration.toFixed(2)} ms`);
JavaScript

ここでやっていることは、

「初期化の開始地点」に init-start というマークを打つ
「初期化の終了地点」に init-end というマークを打つ
init-startinit-end の間を init-duration という名前で測る

という流れです。

performance.now() で前後を測るのと似ていますが、
「名前付きの区間」として残せるのが大きな違いです。

なぜ mark / measure を使うと“整理された計測”になるのか

アプリが大きくなると、
測りたい場所が増えていきます。

初期化
API 呼び出し
画面の描画
特定のユーザー操作の処理

これを全部 performance.now() の前後で測ると、
どこで何を測っているのか分かりにくくなります。

performance.mark / measure を使うと、

「init-duration」
「fetch-user-duration」
「render-dashboard-duration」

のように、
「どの区間を測ったのか」が名前で一目で分かる ようになります。

さらに、performance.getEntriesByName
同じ名前の計測結果をまとめて取れるので、
「この区間は平均どれくらいかかっているか」
といった分析もしやすくなります。


console.time と mark/measure の使い分け

ざっくりした目安

感覚としては、こう捉えると分かりやすいです。

「とりあえずこの処理の時間をサクッと見たい」
console.time / console.timeEnd

「アプリの中の複数の区間を整理して測りたい」
performance.mark / performance.measure

例えば、開発中に

「このループ、重そうだな」
と思ったときは console.time で十分です。

console.time("loop");

for (let i = 0; i < 1000000; i++) {
  // 何か処理
}

console.timeEnd("loop");
JavaScript

一方で、

「ページの初期化全体」
「API 呼び出し部分」
「描画部分」

みたいに、
アプリの構造に沿って区間を測りたい ときは
mark / measure の方が向いています。


少しだけ実践寄りの例: 「画面表示までの時間」を測る

初期化のどこで時間を食っているかを見る

例えば、こんな初期化コードがあるとします。

async function initPage() {
  await loadUser();
  await loadSettings();
  renderUI();
}
JavaScript

これを「どこで時間を食っているか」分解して測ってみます。

async function initPage() {
  performance.mark("init-start");

  performance.mark("load-user-start");
  await loadUser();
  performance.mark("load-user-end");
  performance.measure("load-user", "load-user-start", "load-user-end");

  performance.mark("load-settings-start");
  await loadSettings();
  performance.mark("load-settings-end");
  performance.measure("load-settings", "load-settings-start", "load-settings-end");

  performance.mark("render-start");
  renderUI();
  performance.mark("render-end");
  performance.measure("render", "render-start", "render-end");

  performance.mark("init-end");
  performance.measure("init-total", "init-start", "init-end");

  const total = performance.getEntriesByName("init-total")[0];
  const user = performance.getEntriesByName("load-user")[0];
  const settings = performance.getEntriesByName("load-settings")[0];
  const render = performance.getEntriesByName("render")[0];

  console.log(`初期化合計: ${total.duration.toFixed(2)} ms`);
  console.log(`ユーザー読み込み: ${user.duration.toFixed(2)} ms`);
  console.log(`設定読み込み: ${settings.duration.toFixed(2)} ms`);
  console.log(`描画: ${render.duration.toFixed(2)} ms`);
}
JavaScript

これを実行すると、例えばこんなログが出ます。

初期化合計: 820.15 ms
ユーザー読み込み: 500.32 ms
設定読み込み: 210.10 ms
描画: 90.05 ms

ここまで来ると、

「体感重い」の正体が
「API が 500ms かかっているから」なのか
「描画が 300ms かかっているから」なのか

数字で見えてきます。

この「分解して測る」という感覚が、
パフォーマンスチューニングの入り口です。


初心者として「計測(time / mark)」で掴んでほしいこと

大事なのは、難しい API を全部覚えることではなく、
「とりあえず測ってみる」習慣を持つこと です。

処理が重そうだと思ったら、
console.time / console.timeEnd を一度挟んでみる。

ページの初期化が遅いと思ったら、
performance.mark / measure
「どこからどこまで」を区間として測ってみる。

それだけで、

「なんとなく遅い」から
「この処理が平均 120ms かかっている」へ
一段レベルアップできます。

パフォーマンスの世界は、
測り始めた瞬間から面白くなります。
そこに timemark/measure を、
あなたの“最初のメジャー”として使ってみてください。

タイトルとURLをコピーしました