インフラ運用・保守をやっていてよく CPU 使用率超過状態に遭遇します。今回はこれが何を意味しているか考えてみます。
最近のサーバでは CPU は数コアを積んでいて top コマンド実行時に “1” キーを入力すると CPU 単位の利用率が表示されます(Linux)。
$ top
top – 21:11:46 up 2 days, 21:26, 1 user, load average: 0.06, 0.08, 0.03
Tasks: 148 total, 1 running, 147 sleeping, 0 stopped, 0 zombie
Cpu(s): 1.7%us, 0.2%sy, 0.4%ni, 97.5%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1546096k total, 1486956k used, 59140k free, 224040k buffers
Swap: 2097136k total, 0k used, 2097136k free, 710312k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 15 0 2072 624 532 S 0.0 0.0 0:00.51 init
2 root RT -5 0 0 0 S 0.0 0.0 0:00.00 migration/0
3 root 34 19 0 0 0 S 0.0 0.0 0:00.30 ksoftirqd/0
top コマンドの後 "1" を入力した例
$ top
top – 21:11:33 up 364 days, 9:59, 2 users, load average: 0.04, 0.05, 0.04
Tasks: 203 total, 1 running, 202 sleeping, 0 stopped, 0 zombie
Cpu0 : 0.3%us, 0.0%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 0.3%us, 0.0%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 0.3%us, 0.0%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1942836k total, 1834760k used, 108076k free, 44452k buffers
Swap: 4194232k total, 1945216k used, 2249016k free, 398084k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2 root 15 0 2300 1068 792 R 1 0.1 0:00.03 top
1 root 15 0 2040 568 536 S 0 0.0 0:09.12 init
どんな処理が CPU に負荷をかけている?
何かのプロセスが異常に CPU 負荷をかけている場合、プログラム内では何が起こっているのでしょうか?
プログラムは通常「入力→処理→出力」に分かれるものと基本的な情報処理試験等で教えられてきました。この通りに全ての処理が流れてゆくのであれば CPU への高負荷は通常考えにくいと言えます。というのはこれも教科書の話しになりますがこの中で一番遅いのは常にハードディスク等の外部記憶装置だからです。
最近は SSD 等ハードディスクも進化していますがそれでも未だ「CPU レジスタ > メモリ > ハードディスク」の関係は変わりません。これらのことを踏まえると処理にも寄りますがハードディスクの所ででデータの待ち行列が発生する可能性が高くなります。
ただ、それでもなお「CPU に負荷がかかる」とはどういった状況でしょうか?それは CPU・メモリ・ハードディスクがある内、CPU を多用した処理がある場面と考えられます。
メモリやハードディスクをあまり経由せず CPU を多用することで CPU を酷使した状態にすることが可能です。例えば、ファイル読み込みやネットワーク経由の読み込みを使わず(プログラム観点で言うと)While ループをし続けて処理をする場面等が該当します(正規表現等)。
これこそ CPU 負荷の原因となっている処理と言え、この CPU 負荷が障害の原因となっているのであればこの処理を見直すことで改善に至る可能性があります。例えば、While 内に sleep を 0.01 秒入れるだけでおそらく CPU への負荷は軽減されるでしょう(一方で処理は劇的に遅くなります)。
コア数の増加によって
最近では CPU コア数が増加し、1つのプログラムがたとえ CPU に負荷をかけていても通常は 1つの CPU に限られます(スレッドや fork しているようであれば別)。その為、最近では 1つの CPU がほぼ 100% に近い状態になっても対して問題にならないことが多いかもしれません。
いずれにせよこれらのことを踏まえて障害対応やアプリケーション開発を行うとより効率よくシステムリソースを使うことができるでしょう。