load averageが高い時の診断 - CPU待ち・I/O待ちの見極め
この記事で解決できること
load averageが高いとき、CPU 待ちか I/O 待ちか を切り分けられる- Linux 特有の load average の定義(I/O 待ちも数える)を理解できる
uptime/top/vmstat/iostatの どこを見れば判定できるか が分かる
結論(最短の切り分け)
uptimeで load average、nprocで CPU コア数を確認し、load > コア数 なら過負荷vmstat 1の r 列(実行待ち)が多ければ CPU 飽和、b 列(停止)とwaが多ければ I/O 待ち- 方向が決まったら CPU 側は
top/ps、I/O 側はiostat -xで犯人を特定
前提(対象環境)
- OS:Ubuntu / 一般的な Linux
- シェル:bash
- ツール:
vmstat/iostat/mpstatはsysstatパッケージに含まれる(未導入ならsudo apt install sysstat)
load average とは何か?数字の意味は?
結論: load average は「実行中+実行待ち+I/O 待ちのプロセス数」の指数移動平均で、
uptimeが表示する 3 つの値は左から 1 分・5 分・15 分平均。
uptime または cat /proc/loadavg で確認する。
$ uptime 14:23:05 up 10 days, 3:42, 2 users, load average: 4.85, 3.12, 1.90
$ cat /proc/loadavg 4.85 3.12 1.90 5/812 23145
3 つの数字は 左から 1 分・5 分・15 分 の平均。並びを比較すると傾向が読める。
- 1 分 > 15 分(例:4.85 / 1.90)→ 負荷は 上昇中
- 1 分 < 15 分 → 負荷は 収束中
- 3 つが近い → 負荷が 定常的に高い
/proc/loadavg の 4 列目 5/812 は「実行中プロセス数 / 全プロセス数」、5 列目は最後に生成された PID。
load average はいくつから「高い」のか?
結論: 絶対値で判断せず CPU コア数と比較する。
load average ÷ コア数が 1.0 を超えると、処理を捌ききれずプロセスが待たされている状態。
load average は「待っているプロセスの数」なので、CPU コア数が多いほど許容値も上がる。
$ nproc 4
- コア数 4 で load average 4.0 → ほぼ 使い切り(待ち行列ゼロに近い)
- コア数 4 で load average 8.0 → 2 倍の過負荷(半分のプロセスが順番待ち)
目安として load ÷ コア数 を使う。
| load ÷ コア数 | 状態 |
|---|---|
| ~0.7 | 余裕あり |
| 0.7~1.0 | 使い切りに近い(要注意) |
| 1.0 超 | 過負荷(待ちが発生) |
これは CPU 飽和の場合の目安。Linux では I/O 待ちも load に乗るため、コア数を超えていても「CPU はヒマ」というケースがある。次節がその切り分け。
なぜ Linux の load average は CPU 使用率と一致しないのか?
結論: Linux の load average は実行可能プロセス(TASK_RUNNING)に加え、割り込み不可の I/O 待ち(TASK_UNINTERRUPTIBLE / D 状態)も数える。だから CPU 使用率が低くても load average は跳ね上がる。
多くの UNIX が「CPU の実行キュー長」だけを load にするのに対し、Linux は割り込み不可スリープ(uninterruptible sleep、ps の D 状態)のプロセスも含める。D 状態は主に ディスク I/O やネットワークストレージの応答待ち で発生する。
このため、次のような一見矛盾した状態が起こりうる。
- load average 8.0 なのに CPU 使用率(us+sy)は 10% → 残りは I/O 待ちで積み上がっている
- ストレージが遅い・NFS がハングした、といった状況で load だけが急騰する
「load average が高い = CPU が忙しい」とは限らない。CPU 飽和と I/O 待ちは原因も対処も別物なので、まず切り分ける。
CPU 待ちか I/O 待ちかをどう見極めるのか?
結論:
vmstat 1の r 列(実行待ち)と b 列(I/O 等で停止)、top の%wa(iowait)を見る。r が大きければ CPU 飽和、b と wa が大きければ I/O 待ち。
手順 1:vmstat で全体傾向を見る
$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 6 0 0 124560 20480 890120 0 0 8 12 210 430 78 12 10 0 0 5 0 0 124100 20480 890120 0 0 0 0 198 410 80 11 9 0 0
注目する列は 2 つ。
r(runnable):CPU を実行中/実行待ちのプロセス数。コア数より継続的に大きい → CPU 飽和b(blocked):I/O 等で割り込み不可スリープ中のプロセス数。大きい → I/O 待ち
CPU 欄の wa(iowait、I/O 完了待ちの割合)も併せて見る。上の例は r=6 でコア数 4 を超え、wa=0 なので CPU 飽和型。
手順 2:top で内訳を確認する
$ top
ヘッダ行の CPU 内訳を見る。
%Cpu(s): 78.0 us, 12.0 sy, 0.0 ni, 10.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
us(user)+sy(system)が高い → CPU 飽和。Pキーで CPU 使用率順に並べ替えて犯人プロセスを特定wa(iowait)が高い → I/O 待ち。CPU はディスク等の完了を待っている
手順 3:I/O 待ちの D 状態プロセスを名指しする
wa が高いときは、どのプロセスが I/O で詰まっているかを ps の状態列(STAT)で探す。
$ ps -eo pid,stat,comm,wchan | awk '$2 ~ /D/'
1842 D mysqld wait_on_page_bits 1990 D+ dd balance_dirty_pages
STAT が D(uninterruptible sleep)のプロセスが I/O 待ちの当事者。wchan(カーネル内の待ち場所)も原因のヒントになる。
手順 4:iostat でディスク側を裏取りする
$ iostat -x 1 3
Device r/s w/s rkB/s wkB/s await aqu-sz %util sda 8.00 420.00 64.00 51200.0 85.20 9.80 99.6
%utilが 100% 近い → そのデバイスが飽和(これ以上 I/O を捌けない)await(1 I/O あたりの平均応答ミリ秒)が大きい → ディスクが遅いaqu-sz(平均キュー長)が大きい → I/O が滞留
%util ほぼ 100% は I/O 待ち型の決め手。
判定チートシート
vmstatのr高・wa低 → CPU 飽和vmstatのb高・top のwa高・iostatの%util高 → I/O 待ち- どちらも高い → CPU と I/O が連鎖(DB の全表スキャン等)。両面から見る
CPU 飽和が原因のときの対処は?
結論: top/ps で CPU を食うプロセスを特定し、暴走なら nice での優先度調整や停止、慢性的ならコア増設・処理の分散・コード最適化を検討する。
$ ps -eo pid,pcpu,comm --sort=-pcpu | head
- 単発の暴走 → 原因プロセスを停止、または
reniceで優先度を下げる - 慢性的にコア数を超える → スケールアップ(コア増設)・処理の並列分散・アルゴリズム改善
- 特定時間帯だけ → cron / バッチの集中を疑い、実行時刻を分散
詳細な犯人特定の手順は CPU100%の調べ方 を参照。
I/O 待ちが原因のときの対処は?
結論: iostat で飽和デバイスを特定し、I/O を出しているプロセスを iotop で見つける。ログ肥大・スワップ多発・遅いストレージが典型要因。
$ sudo iotop -o
- 特定プロセスの書き込みが多い → ログ出力過多・全表スキャン等を疑う
si/so(vmstat のスワップ列)が動いている → メモリ不足でスワップ多発。メモリ不足の調べ方 へ- ストレージ自体が遅い → デバイス交換・I/O スケジューラ見直し・読み書きの削減
ディスク I/O の深掘りは ディスクI/Oが遅いときの調べ方 を参照。
やってはいけないこと
- load average の 絶対値だけ で判断する(コア数を必ず併記)
waを無視して CPU 増設に走る(I/O 待ちはコアを足しても解決しない)- D 状態プロセスを
kill -9で無理に止めようとする(I/O 完了まで止まらないことが多い)