← システム性能分析のしくみ コース
2. 飽和の膝 — なぜ使用率90%から急に遅くなるのか
使用率が上がるにつれて待ち時間がどう伸びるのかを、図で追っていきましょう。
① まず「使用率」とは何を測った数字か
観測期間たとえば1秒
そのうち資源が仕事をしていた時間の割合
使用率 ρ = busy時間 ÷ 経過時間0.0〜1.0(0%〜100%)
Linuxでの実例
iostat の %utilデバイスにI/O要求が発行されていた経過時間の割合
man iostat(1)/sys/block/<dev>/stat の io_ticksI/O要求がキューにあったミリ秒の累計
docs.kernel.org- ・iostat(1) は %util を「I/O要求が発行されていた経過時間の割合(デバイスの帯域使用率)」と定義しています。
- ・カーネル文書は io_ticks を「デバイスにI/O要求がキューされていたミリ秒数」と定義しています。「活動中の時間」ではなく「要求を抱えていた時間」です。
- ・使用率は「どれだけ忙しかったか」であって「どれだけ速いか」ではありません。ここが後の話の出発点です。
使用率は、資源が仕事をしていた時間の割合です。まずこの1つの数字の意味を固定しておきます。
② 使用率が上がると、なぜ待ちが生まれるのか
要求が到着到着間隔はばらつく
資源が空いていれば
すぐ処理開始待ち時間 0
資源が前の仕事で塞がっていれば
キューで待つ待ち時間が発生
待ち込みの所要時間として観測される
応答時間 = 待ち時間 + 処理時間iostat の await がまさにこれ
- ・iostat(1) の await は「キューで過ごした時間とサービスされた時間の両方を含む」平均時間(ミリ秒)と定義されています。
- ・使用率が高いほど「到着したときに塞がっている確率」が上がるため、待ちに入る割合が増えます。
待ちは、到着したときに資源が塞がっていると発生します。使用率とは、まさにその「塞がっている確率」です。
③ 待ち時間は 1/(1-ρ) で伸びる
ρ = 0%応答時間 1.0倍
ρ = 30%応答時間 1.4倍
ここまでは、ほぼ処理時間そのもの
ρ = 50%応答時間 2.0倍
ρ = 60%応答時間 2.5倍
じわじわ伸び始める
ρ = 70%応答時間 3.3倍
ρ = 80%応答時間 5.0倍
ここから跳ね上がる
ρ = 90%応答時間 10.0倍
ρ = 95%応答時間 20.0倍
ρ→1 で発散
ρ = 98%応答時間 50.0倍
- ・これは待ち行列理論のM/M/1(到着も処理もランダム、窓口1つ)という基本モデルの結果です。
- ・分母が (1-ρ) なので、ρが1に近づくほど値が急激に大きくなります。これが「膝」の正体です。
- ・実際のシステムはM/M/1そのものではありませんが、「分母に余裕が入る」形は共通で、傾向の目安として使えます。
分母が「余っている割合」なので、余裕が減るほど倍率が跳ね上がります。曲線ではなく段として並べると、後半の急変がよく見えます。
④ 同じ「10ポイント」でも意味がまるで違う
50% → 60%2.0倍 → 2.5倍
所要時間は25%増同じ10ポイントでも
70% → 80%3.3倍 → 5.0倍
所要時間は50%増同じ10ポイントでも
80% → 90%5.0倍 → 10.0倍
所要時間は2倍わずか5ポイントで
90% → 95%10.0倍 → 20.0倍
所要時間は2倍- ・50%→60%は所要時間が25%増える程度ですが、90%→95%はたった5ポイントで倍になります。
- ・つまり「使用率をあと10ポイント足せるか」の答えは、いま何%にいるかで完全に変わります。
使用率の1ポイントの重みは一定ではありません。高いところほど1ポイントが高くつきます。
⑤ 「まだ80%だから余裕」が危ういのはなぜか
現状 ρ = 80%応答時間 5.0倍。監視上はまだ緑
到着が約19%増えると
ρ = 95%応答時間 20.0倍
つまり
入力は約2割増利用者から見れば普通の増加
応答は4倍悪化5.0倍から20.0倍へ
- ・ρ は到着レートに比例するため、到着が18.75%増えれば 0.80 × 1.1875 = 0.95 になります。
- ・使用率という指標は上限が100%で頭打ちになるので、グラフ上は「まだ余地がある」ように見えてしまいます。
- ・平均使用率が低くても、短時間のバーストで瞬間的に100%に達していれば待ちは発生します。長い観測間隔はこれを隠します。
使用率は線形に見える指標ですが、その先の応答時間は非線形です。残り20%は「性能の余裕が20%残っている」という意味ではありません。
⑥ ばらつきが大きいほど、膝は手前に来る
ばらつきが小さい到着間隔も処理時間もほぼ一定
例: 規則的なバッチばらつきが大きい到着も処理時間も大きく揺れる
例: ランダムなI/O混在同じ使用率で比べると
待ちは発生しにくい膝は100%寄り
待ちが発生しやすい膝は手前に来る
結果として安全に運用できる使用率は
高めでも耐えるばらつきが小さい前提が必要
低めに抑える必要がある揺らぎの分だけ余裕を積む
- ・待ち行列の一般的な結果として、待ち時間は到着間隔と処理時間のばらつきが大きいほど増えます。
- ・③で示した 1/(1-ρ) は、到着も処理もランダムなM/M/1という「ばらつきがある側」の目安です。
- ・ばらつきが小さい系ならこれより緩やかになり、逆に処理時間の分布が偏るとさらに厳しくなります。
膝の位置は使用率だけでは決まりません。同じ80%でも、揺らぎの大きい系のほうが先に苦しくなります。
⑦ だから目標使用率は100%より十分低く置く
目標を応答時間で決める「〇〇ミリ秒以内」を先に置く
その応答時間を満たす使用率まで逆算する
目標使用率を設定膝より十分手前に置く
使用率だけでなく飽和側も併せて見る
iostat の aqu-szデバイスに発行された要求の平均キュー長
待ちの量そのものiostat の await待ち時間を含む平均所要時間
体感に近い判断
%util が高くても aqu-sz が小さい詰まってはいない
aqu-sz と await が伸びている膝に入りかけている
- ・iostat(1) は aqu-sz を「デバイスに発行された要求の平均キュー長」と定義しています。
- ・重要な前提として iostat(1) は、%util が飽和を意味するのは要求を逐次処理するデバイスだけで、RAIDアレイや近年のSSDのように並列処理するデバイスでは %util はその性能限界を反映しないと明記しています。並列デバイスでは %util ではなく aqu-sz と await で判断してください。
- ・ディスクのように処理を中断できない資源については、使用率が70%を超えるとキュー遅延が目立ちやすくなるとUSE methodのページで述べられています。
- ・使用率(どれだけ忙しいか)と飽和(どれだけ待たされているか)は別の指標なので、両方を並べて見るのが安全です。
使用率を目標にするのではなく、応答時間を目標にして使用率を逆算します。%util と aqu-sz を並べて見るのが実践的な確認方法です。