手軽屋
ツール一覧

performance.now()技術仕様: 反応時間計測になぜサブミリ秒精度が必要か

MDN Web Docs記載のW3C High Resolution Time仕様をベースに、反応速度ツール製作者・Web開発者向けに精度と落とし穴を解説します。

performance.now()とは何か

Performance.now()はW3C High Resolution Time Level 2仕様で定義されたDOMHighResTimeStamp型の時刻取得APIです。 単位はミリ秒、戻り値はdouble(倍精度浮動小数点数)で、サブミリ秒の精度を表現できます。

値はtime origin(ドキュメント生成時刻)からの経過時間で、常に単調増加(monotonic)が保証されています。 システム時計を変更しても値が逆行することはありません。

Date.now()との違い

項目performance.now()Date.now()
精度サブミリ秒(0.005〜1ms)ミリ秒整数
基準ドキュメント生成時刻UNIXエポック(1970-01-01)
単調性常に単調増加システム時計次第で逆行可
用途経過時間測定絶対時刻表示

Spectre対策で精度が切り下げられた歴史

2018年のSpectre/Meltdown脆弱性発覚を受け、各ブラウザはperformance.now()の精度を一時的に大幅に下げました。 ChromeはSharedArrayBuffer無効時に100μs(0.1ms)刻み、Firefoxは1ms刻みまで切り下げました。

現在はCross-Origin-Opener-PolicyCross-Origin-Embedder-Policyを両方有効にしたcross-origin isolated環境でのみ、サブミリ秒精度(約5μs)が解禁されます。 反応速度ツールは数百msオーダーで動くため、デフォルトの100μs精度でも実用上問題ありません。

⚠️ JS時刻測定で取れない遅延

performance.now()がいくら高精度でも、人間が画面で見て反応するまでには以下の遅延が乗ります:

合計で20〜35msのオフセットが必ず乗ります。「他人との比較」には使えず、「自分の経時変化」にのみ意味があります。

反応時間計測の最小実装

let readyAt = 0;
button.onclick = () => {
  const ms = performance.now() - readyAt;
  console.log(`${Math.round(ms)} ms`);
};
// 緑表示と同時に
readyAt = performance.now();

本ツール反応速度テストもこの構造です。緑への切替直後のperformance.now()を基準点とし、クリック時の差分をms表示します。

関連