← システム性能分析のしくみ コース
4. ロードアベレージ — Linuxでは何を数えているのか
Linuxのロードアベレージが実際に何を数えているのかを、図で追っていきましょう。
① ロードアベレージはどこから読めるのか
$ cat /proc/loadavgカーネルが提供する擬似ファイル
中身は1行・5フィールド
0.52第1フィールド
1分平均0.83第2フィールド
5分平均1.14第3フィールド
15分平均残りの2フィールドは平均値ではない
2/431第4フィールド
実行可能な数 / 存在する総数18942第5フィールド
直近に生成されたPID- ・proc(5) は第1〜第3を「1分・5分・15分で平均した値」と定義しています
- ・第4フィールドはスラッシュ区切りで、前半が「現在実行可能なカーネルスケジューリングエンティティ(プロセス・スレッド)の数」、後半が「システムに現在存在する数」です
- ・第5フィールドは平均でも負荷でもなく、最後に作られたプロセスのPIDです
最初の3つだけが「ロードアベレージ」です。第4・第5は同じ行に並んでいるだけの別物なので、混同しないようにします。
② 3つの数値は「時間の窓」が違うだけ
数えている対象どの窓でも同一
それを3つの窓で平均する
1分平均直近の変化に敏感
急変を捉える5分平均中間
15分平均直近の変化に鈍い
傾向を捉える3つを並べると傾向が読める
1分 > 15分負荷が上がってきている
上昇中1分 < 15分負荷が下がってきている
収束中- ・3つの値は別々の指標ではなく、同じ対象を異なる長さの窓で平均したものです
- ・そのため1分値と15分値の大小関係から、負荷が増加中か減少中かの向きが読めます
3つ並んでいるのは「今」と「さっきまで」を比べさせるためです。1つだけ見ても向きは分かりません。
③ 平均の中身は指数移動平均
一定間隔でタスク数を観測カーネルが定期的にサンプリング
単純平均ではなく指数移動平均で更新
直前までの平均値1より小さい係数を掛けて減衰させる
今回観測した数残りの重みで足し込む
この性質から挙動が決まる
急に負荷がかかっても値はすぐには跳ね上がらない
じわっと上がる負荷が消えても値はすぐには0に戻らない
尾を引く- ・proc(5) が定めているのは「1分・5分・15分で平均する」ことまでです。指数移動平均で更新する実装はカーネルの kernel/sched/loadavg.c 側にあります
- ・窓が長いほど減衰が緩やかになるため、15分値は過去の負荷を長く引きずります
負荷が消えた直後でもロードアベレージが高いままなのは、平均が過去を減衰させながら引きずる仕組みだからです。「今この瞬間の混雑度」ではありません。
④ Linuxが数える対象には D 状態が含まれる
システム上の全タスクプロセス・スレッド
状態で振り分ける
R 状態running or runnable
数えるD 状態uninterruptible sleep
数えるS 状態interruptible sleep
数えないZ / T 状態zombie / stopped
数えないR と D の合計を平均したものが
ロードアベレージCPUの使用率ではない
- ・proc(5) は集計対象を「ランキュー内(R状態)、またはディスクI/O待ち(D状態)のジョブ数」と定義しています
- ・ps(1) の PROCESS STATE CODES では、D は「uninterruptible sleep (usually I/O)」、R は「running or runnable (on run queue)」です
- ・S 状態(interruptible sleep)はシグナルで起こせる待ちで、集計対象に入りません
ここが最重要点です。CPUを待っている R だけでなく、ディスクI/Oを待って中断不可能に眠っている D も同じ1として数えられます。
⑤ だから「高い=CPUが混雑」とは限らない
ロードアベレージ 8.0この数値だけでは原因が分からない
内訳を分解すると2通りありうる
平均すると R が 8 / D が 0CPUの取り合いが起きている
CPU側の問題平均すると R が 0 / D が 8I/O完了をひたすら待っている
ストレージ側の問題後者ではCPUは
ほとんど遊んでいるそれでもロードアベレージは8.0
CPU増設は効かない- ・R と D の合算値であるため、ロードアベレージ単体ではどちらが原因か区別できません
- ・D 状態はシグナルで中断できない待ちであり、多くはブロックデバイスへのI/O完了待ちです
ロードアベレージが高いという事実だけでCPU増設を判断すると、原因がI/O側だった場合に何も改善しません。必ず内訳へ降ります。
⑥ 切り分けは vmstat の r 列と b 列を分けて見る
$ vmstat 11秒間隔でサンプリング
Procs セクションの2列に注目
r 列runnable processes (running or waiting for run time)
実行中または実行待ちb 列processes blocked waiting for I/O to complete
I/O完了待ちでブロック中どちらが大きいかで進む先が変わる
r が大きいCPU側を掘る
実行待ち行列が長いb が大きいストレージ側を掘る
I/O完了が遅い- ・vmstat(8) は r を「The number of runnable processes (running or waiting for run time)」、b を「The number of processes blocked waiting for I/O to complete」と定義しています
- ・vmstat(8) は「最初のレポートは前回の再起動以来の平均値」と明記しています。現在の状態を見る際は2行目以降を読みます
ロードアベレージが合算してしまった R と D を、vmstat は r と b に分けて見せてくれます。最初の1行を読み飛ばすのを忘れないでください。
⑦ PSI なら「待たされた時間の割合」で見られる
/proc/pressure/cpuCPU待ちによる停滞
/proc/pressure/ioI/O待ちによる停滞
/proc/pressure/memoryメモリ逼迫による停滞
各ファイルは some と full の2行を持つ
some一部のタスクが停滞していた時間の割合
full非アイドルの全タスクが同時に停滞していた割合
各行のフィールド
avg1010秒平均
avg6060秒平均
avg300300秒平均
total累計停滞時間(マイクロ秒)
- ・カーネル公式ドキュメント accounting/psi によれば、some は「少なくとも一部のタスクがそのリソースで停滞していた時間の割合」、full は「非アイドルの全タスクが同時に停滞していた時間の割合」です
- ・cpu の full はシステム全体では定義されない値ですが、5.13 以降は報告され続けているため後方互換としてゼロが設定されます
- ・リソースごとにファイルが分かれているため、CPUとI/Oのどちらで待たされたかが最初から区別されています
ロードアベレージが「数」なのに対し、PSIは「待たされた時間の割合」です。しかもリソース別に分かれているため、切り分けの手間が最初から省けています。