「計測」は“なんとなく遅い”を数字に変えるための技術
パフォーマンスの話で一番大事なのは、
「速い/遅い」を 感覚ではなく数字で話せるようになること です。
そのために使うのが、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"); // スペルミス → 結果が出ない
JavaScriptconsole.time と console.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-start と init-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 かかっている」へ
一段レベルアップできます。
パフォーマンスの世界は、
測り始めた瞬間から面白くなります。
そこに time と mark/measure を、
あなたの“最初のメジャー”として使ってみてください。
