LESSON 15分

ストーリー

高橋アーキテクト
このforループを最適化すれば速くなるはずです

高橋アーキテクトは眉をひそめた。

高橋アーキテクト
“はず”? 計測したのか?
あなた
いえ、直感で…
高橋アーキテクト
パフォーマンスエンジニアリングの鉄則がある。“推測するな、計測せよ(Don’t guess, measure)“。直感は驚くほど当てにならない。必ずデータに基づいて判断しろ

鉄則:推測するな、計測せよ

なぜ直感は当てにならないか

// どちらが速いと思いますか?

// パターン A: forループ
function sumA(arr: number[]): number {
  let sum = 0;
  for (let i = 0; i < arr.length; i++) {
    sum += arr[i];
  }
  return sum;
}

// パターン B: reduce
function sumB(arr: number[]): number {
  return arr.reduce((acc, val) => acc + val, 0);
}

// 答え: 環境、データサイズ、JITの最適化状態によって異なる
// 計測しなければ分からない

計測の基本手法

// 1. console.time / console.timeEnd(簡易計測)
console.time('process');
await processData();
console.timeEnd('process'); // process: 142.5ms

// 2. performance.now()(高精度計測)
const start = performance.now();
await processData();
const elapsed = performance.now() - start;
console.log(`${elapsed.toFixed(2)}ms`);

// 3. ベンチマーク関数(複数回実行して統計を取る)
async function benchmark(
  fn: () => Promise<void>,
  iterations: number = 100
): Promise<{ avg: number; p50: number; p95: number; p99: number }> {
  const results: number[] = [];

  for (let i = 0; i < iterations; i++) {
    const start = performance.now();
    await fn();
    results.push(performance.now() - start);
  }

  results.sort((a, b) => a - b);

  return {
    avg: results.reduce((a, b) => a + b, 0) / results.length,
    p50: results[Math.floor(results.length * 0.5)],
    p95: results[Math.floor(results.length * 0.95)],
    p99: results[Math.floor(results.length * 0.99)],
  };
}

計測の3原則

1. 本番に近い環境で計測する

開発環境と本番環境ではパフォーマンス特性が全く異なります。

要素開発環境本番環境
データ量数百件数百万件
同時接続数1人数千人
ネットワークローカルインターネット経由
リソース開発マシン本番サーバー

2. 統計的に有意なデータを取る

// 悪い例:1回だけ計測
const result = await measureOnce(); // 信頼性が低い

// 良い例:複数回計測して統計を取る
const results = await benchmark(fn, 1000);
// ウォームアップを含め、外れ値を除外する

3. 変更前後で比較する

// A/Bテスト的にパフォーマンスを比較
interface ComparisonResult {
  before: BenchmarkResult;
  after: BenchmarkResult;
  improvement: string; // "+15% faster"
}

function compare(
  before: BenchmarkResult,
  after: BenchmarkResult
): ComparisonResult {
  const improvement = ((before.p50 - after.p50) / before.p50) * 100;
  return {
    before,
    after,
    improvement: `${improvement > 0 ? '+' : ''}${improvement.toFixed(1)}% ${improvement > 0 ? 'faster' : 'slower'}`,
  };
}

まとめ

ポイント内容
鉄則推測するな、計測せよ
原則1本番に近い環境で計測する
原則2統計的に有意なデータを取る
原則3変更前後で比較する

チェックリスト

  • 「推測するな、計測せよ」の意味を理解した
  • 基本的な計測手法を把握した
  • 計測の3原則を説明できる

次のステップへ

Step 1 の総まとめとして、理解度チェックに挑みましょう。パフォーマンスエンジニアリングの基礎知識を確認します。


推定読了時間: 15分