0. この記事は

・初心者向けの記事です。
・初めて寄稿した記事です。
・正しいLinuxシステムの監視のため、ふわっとしがちな概念をきちんと理解することを目指す記事です。

1. Load Averageとは

1-1. 疑問

最近俄かに界隈を騒がせた(?)『入門 監視 モダンなモニタリングのためのデザインパターン』(Mike Julian著)に以下のような一節が記されています。

問題なのは、ロードの数値はシステムパフォーマンスを表しているわけではないことです。

おや?という気分になりませんか?
ロード(負荷)って言ってるではないか、この値がシステムパフォーマンスを表していなかったら一体何なんだ、と。

1-2. 問題の定式化

手始めに、初心者向けのサイトを漁りながらLoad Averageとは結局何なのか、調べてみました。
僕に理解できるレベル感の文献であれば、その多くが以下のような記述となっています。

“Load Averageとは「CPUの処理を待っているプロセスがいくつあるか」を表す指標です。”

僕の今までの認識とは殆ど隔たりはありませんが、確かに曖昧と言われれば曖昧かもしれません。
この説明が正しいとするならば、Load Averageとは何か、という問いは

・プロセスがCPUの処理を待っているとはどういう状態か?
・プロセスがCPUの処理を待たされる原因は何か?

に答えられれば(少なくとも部分的には)解決できそうです。

※以下では簡単のため、ハイパースレッディングや論理コアといった話は扱いません。
つまり、ここではCPUはとても単純化された機械を想定します。
機械のパーツとしてのCPUが1つあって、それは”多面指し”をしても”一人二役”をしません。

2. プロセス

2-1. そもそもプロセスとは何か

プロセスとはOS上でタスクを実行する実体です。
一方、似たような概念にプログラムというものがありますが、こちらはあくまで実行イメージであり
ディスク上に保存されている命令とデータのセットです。
あるいはプログラムは実行時にどのようなプロセスを生成するかを記述したファイルとも言えます。

つまり、雑な言い方をするとプロセスは「実行中」のプログラムと言えます。

2-2. Load Averageとプロセスの関係

さて、プロセスは「実行中」のプログラムだと書きましたが、もう少し細かく見てみましょう。
プロセスは実行されるとメモリ上に必要な領域を確保して読み込まれ、順次CPUによって処理されます。
そして、ある一瞬を切り取れば、1つの物理的なCPUを占有できるのは1つのプロセスだけです。
ではなぜ、我々ユーザから見てプロセスは並行して実行されているように見えるのかと言うと
カーネルがCPUを割り当てるプロセスを一定時間ごとに(強制的に)切り替えているからです。

これを高速で行うことで、我々には宛もプロセスが並行して実行されているかのように見えます。
ちょうど将棋の多面指しのような状態です。


※Linuxではスケジューリングモデルとして「ラウンドロビンタイムシェアリング」を採用しています。
この方法では全てのプロセスを順番に、決められた時間だけCPUで実行します。(この時間をタイムスライスと呼びます。)
そして、このラウンドロビンタイムシェアリングでは、プロセスからはいつどれだけCPUを使用できるかを制御することはできません。
デフォルトでは全てのプロセスは順にCPUを与えられ、タイムスライスを使い切るか自らCPUを手放す(後述のプロセスの状態遷移)までCPUを使用し続けます。


では、CPUが割り当たっていない間のプロセスは何をしているのでしょうか。

ここで先ほどの「実行中」という表現を少し詳しく見る必要が出てきます。
と言うのも、「実行中」のプロセスにはいくつかの状態が存在するためです。
簡単のため、以下のような状態モデルを考えます。

実行可能/TASK_RUNNING:
CPUが割り当たれば実行されます。
また、実際にCPUが割り当たっていないものを明示的にTASK_RUNNING(Ready)などと呼ぶことで区別することもあります。

イベント待ち(割り込み可能)/TASK_INTERRUPTABLE:
イベントを待っている状態のうち、シグナルでの割り込みなどで待ち状態が解除されるものです。ユーザ操作待ちやパケット受信待ちがこれに当たります。
この状態の待ち状態は通常、復帰時間が予測できません。

イベント待ち(割り込み不可)/TASK_UNINTERRUPTABLE:
イベントを待っている状態のうち、シグナルでの割り込みなどで待ち状態が解除されないものです。IO待ちなどがこれに当たります。
この状態の待ち時間は通常、短時間で復帰することが期待されます。

停止中/TASK_STOPPED:
シグナルを受信したことで停止している状態です。

ゾンビ/TASK_ZOMBIE:
プロセス終了後に親プロセスが終了状態を受け取るのを待っている状態です。

上記の状態を考えるとき、OS上で実行されている多くのプロセスはCPUが割り当たって実行されている状態と、割当を待っている状態を行き来することが分かります。

そして、このような状態モデルでLoad Averageの値に反映されるのは
実行可能/TASK_RUNNING(Ready)
・イベント待ち(割り込み不可)/TASK_UNINTERRUPTABLE

の2つです。

これらを踏まえると、例えば以下が言えるでしょう。

・何かを計算するプログラムをいくつも走らせている場合、CPU割り当てを待つプロセスが存在するため、Load Averageは上がります。

・viなどのエディタを開いているときはユーザ入力待ちが殆どの時間を占めるのでLoad Avereageはなかなか上がりません。

3. 結局、Load Averageとは

これまでの内容から、初めの問いの答えは以下のようになります。

  1. プロセスがCPUの処理を待っているとはどういう状態か?
    ⇒CPUの割当があればすぐに実行できる状態で「待っている」場合と、ディスクなどへのIOが完了するのを「待っている」状態

  2. プロセスがCPUの処理を待たされる原因は何か?
    ⇒実は「処理待ち」にもLoad Averageに含まれる「待ち」とそうでない「待ち」が存在しており、前者で言えば、CPUの割り当てやディスク、NFSのIOが間に合っていないことが原因

これらを踏まえた上での
「CPUの処理を待っているプロセスがいくつあるか」
あたりがLoad Averageについての(より)正しい認識になるのではないでしょうか。

4. まとめ

再び冒頭の引用に戻ります。

問題なのは、ロードの数値はシステムパフォーマンスを表しているわけではないことです。

実は『入門 監視 モダンなモニタリングのためのデザインパターン』には以下のような一節も含まれます。

しかし、ロードアベレージは代理指標(proxy metric)として役立つという例外があります。つまり、異常に高いロードアベレージは、他の問題の存在を示すことがある(そうでない場合もありますが)という意味です。

これらはつまり(繰り返しに近いですが)
・Load Averageが高いことがシステムパフォーマンスが低いことには直結しない。
・Load Averageが高いことの原因(例えばディスクへの書込み待ちが多発している)がシステムパフォーマンスの低下を招き得る。
あたりに換言されそうです。

いずれにせよ、提供しているサービスの特性、使われている技術、そのアーキテクチャを知らないと「処理が詰まっている」という症状すら具体的にどんな状態かは分かりません。

月並みですが、「Load Average 高い」でググって何となくで監視するのは止めましょう、というお話でした。

関連記事

この記事へのコメント

まだコメントはありません
3
メモ以上ブログ未満
3
このエントリーをはてなブックマークに追加