パフォーマンスの法則(発展)
パフォーマンスを定量的に理解するための法則を学びます。基礎を理解した後に読むことをお勧めします。
┌─────────────────────────────────────────────────────────────┐
│ 「なんとなく」を「数字」に変える │
├─────────────────────────────────────────────────────────────┤
│ │
│ 「接続プール、何個必要?」 │
│ 「サーバー増やせばどのくらい速くなる?」 │
│ │
│ こういう質問に「勘」で答えていないか? │
│ │
│ 法則を知っていれば、計算で見積もれる。 │
│ │
└─────────────────────────────────────────────────────────────┘
リトルの法則
┌─────────────────────────────────────────────────────────────┐
│ L = λ × W │
├─────────────────────────────────────────────────────────────┤
│ │
│ L = システム内の平均リクエス ト数(同時処理数) │
│ λ = 到着率(スループット、req/sec) │
│ W = 平均滞在時間(レイテンシ、sec) │
│ │
│ 言い換えると: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 同時処理数 = スループット × レイテンシ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
具体例で理解する
┌─────────────────────────────────────────────────────────────┐
│ 例1: 接続プールの見積もり │
├─────────────────────────────────────────────────────────────┤
│ │
│ 状況: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ・100 req/sec のトラフィック │ │
│ │ ・1リクエストあたりDB処理に 50ms かかる │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 計算: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ L = 100 × 0.05 = 5 │ │
│ │ │ │
│ │ → 常に5つのDB接続が使用中 │ │
│ │ → 接続プールは最低5個必要 │ │
│ │ → 余裕を見て 10-15個 に設定 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 例2: スレッドプールの見積もり │
├─────────────────────────────────────────────────────────────┤
│ │
│ 状況: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ・1000 req/sec を処理したい │ │
│ │ ・1リクエストの処理に 100ms かかる │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 計算: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ L = 1000 × 0.1 = 100 │ │
│ │ │ │
│ │ → 100スレッド必要 │ │
│ │ → スレッドプールは最低100に設定 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
逆算にも使える
┌─────────────────────────────────────────────────────────────┐
│ 「接続プール10個で何req/sec捌ける?」 │
├─────────────────────────────────────────────────────────────┤
│ │
│ L = λ × W を変形すると: │
│ λ = L / W │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 接続プール: 10個 │ │
│ │ DB処理時間: 50ms │ │
│ │ │ │
│ │ λ = 10 / 0.05 = 200 req/sec │ │
│ │ │ │
│ │ → 最大200 req/sec まで処理可能 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
アムダールの法則
┌─────────────────────────────────────────────────────────────┐
│ 並列化の限界 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 全体の高速化 = 1 / ((1-P) + P/N) │
│ │
│ P = 並列化できる部分の割合 │
│ N = 並列度(CPUコア数、サーバー台数など) │
│ │
│ 言い換えると: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 並列化できない部分が、全体の速度の上限を決める │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
具体例で理解する
┌─────────────────────────────────────────────────────────────┐
│ 例: 処理の90%が並列化可能な場合 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 処理全体: █ ███████████████████ 100% │ │
│ │ 並列化可能: ██████████████████ 90% │ │
│ │ 並列化不可: ██ 10% │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ CPUを増やすとどうなる? │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ CPU 1コア: 1 / (0.1 + 0.9/1) = 1倍 (基準) │ │
│ │ CPU 2コア: 1 / (0.1 + 0.9/2) = 1.82倍 │ │
│ │ CPU 4コア: 1 / (0.1 + 0.9/4) = 3.08倍 │ │
│ │ CPU 8コア: 1 / (0.1 + 0.9/8) = 4.71倍 │ │
│ │ CPU 16コア: 1 / (0.1 + 0.9/16) = 6.40倍 │ │
│ │ CPU ∞コア: 1 / (0.1 + 0) = 10倍 ← 上限! │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ どれだけCPUを増やしても10倍が限界 │
│ (並列化できない10%がボトルネック) │
│ │
└─────────────────────────────────────────────────────────────┘
何を教えてくれるか
┌─────────────────────────────────────────────────────────────┐
│ アムダールの法則の教訓 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 教訓1: ボトルネックを解消しないと意味がな い │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 並列化できない部分が10%でも、上限は10倍 │ │
│ │ その10%を改善しない限り、CPU追加は無駄 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 教訓2: サーバー追加には限界がある │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 「遅いからサーバー倍にしよう」 │ │
│ │ → ボトルネックがあれば2倍にならない │ │
│ └───────────────────────── ────────────────────────────┘ │
│ │
│ 教訓3: 並列化できない部分を見つけることが重要 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ・共有リソースへのアクセス(DB、ファイル) │ │
│ │ ・ロック待ち │ │
│ │ ・直列化が必要な処理 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘