Dev Study
システム性能分析のしくみ コース

4. ロードアベレージ — Linuxでは何を数えているのか

Linuxのロードアベレージが実際に何を数えているのかを、図で追っていきましょう。

① ロードアベレージはどこから読めるのか

/proc/loadavg の 5 つのフィールド
$ 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つの数値は「時間の窓」が違うだけ

同じ対象を1分・5分・15分の窓で平均している
数えている対象どの窓でも同一
それを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 状態が含まれる

proc(5) が定義する集計対象
システム上の全タスクプロセス・スレッド
状態で振り分ける
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 でも原因が違う
ロードアベレージ 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 は R と D を別の列に分けて出す
$ 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 はリソース別に停滞時間を出す
/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は「待たされた時間の割合」です。しかもリソース別に分かれているため、切り分けの手間が最初から省けています。

公式ドキュメントで詳しく ↗