1. ryuichi1208

    No comment

    ryuichi1208
Changes in title
-Linux Load Averageの算出方法
+Linux:Load Averageの算出方法
Changes in body
Source | HTML | Preview
@@ -1,121 +1,135 @@
![20150307003237.jpg](https://qiita-image-store.s3.amazonaws.com/0/258841/4e3e5465-3d63-84cf-ada4-24d11068149e.jpeg)
## 背景
+CPU使用率だったりAverageLoadだったりを見てサーバの負荷度だったりを調査する必要があってそれについていろいろ疑問だった点をまとめました。間違い等あればご指摘お願いします。
+
+https://github.com/torvalds/linux
+
## Load Averageって?
ロードアベレージはシステム全体の負荷状況を表す指標。
「1CPUにおける単位時間あたりの実行待ちとディスクI/O待ちのプロセスの数」で表される。
Linuxカーネルはプロセス1つごとにプロセスディスクリプタを持っている。
Linuxでのプロセスディスクリプタはtask_struct構造体という名前になっていて、プロセスに関する全ての情報が入っています。
以下はtask_structの実装の一部です。
``` c:include/linux/sched.h
struct task_struct {
// コンテキストスイッチ時にスタックポインタ、インストラクションポインタなどを保存する領域
struct thread_info thread_info;
// プロセスの状態
volatile long state;
// 優先度
int prio;
// プロセスの仮想メモリ空間に関する情報(ページテーブルなど)を記録
struct mm_struct *mm;
+
+ // 他にもいろいろとプロセスに関する情報を保持している
+ int static_prio;
+ int normal_prio;
+ unsigned int rt_priority;
+ int exit_state;
+ int exit_code;
+ int exit_signal;
}
```
システムで実行中のプロセスは、IO待ちなどにより一時的に実行を中断している状態などがあります。
以下はプロセスの状態です。
* TASK_RUNNING: 実行中・実行待ちの状態
* TASK_STOPPED: 実行中断になった状態
* TASK_ZOMBIE: ゾンビプロセス
* TASK_UNINTERRUPTABLE: 割り込み不能な待ち状態
* TASK_INTERRUPTABLE: 割り込み可能な待ち状態。ハードウェア割り込み、システム資源の解放、シグナルなどの要因により起床
今回取り上げるLoad Averageは上記のうちRUNNINGとUNINTERRUPTABLEの和がLoad Averageとなっています。
アクティブなプロセス数の算出をしている処理。
``` c:kernel/sched/loadavg.c
long calc_load_fold_active(struct rq *this_rq, long adjust)
{
long nr_active, delta = 0;
nr_active = this_rq->nr_running - adjust;
nr_active += (long)this_rq->nr_uninterruptible;
if (nr_active != this_rq->calc_load_active) {
delta = nr_active - this_rq->calc_load_active;
this_rq->calc_load_active = nr_active;
}
return delta;
}
```
## Load Averageを確認する
Load Averageは以下のコマンドで確認できます
* uptime
* w
* top
* sar
+## CPU使用率とLoadAverageの違い
+
## 算出方法
``` c:kernel/sched/loadavg.c
void calc_global_load(unsigned long ticks)
{
unsigned long sample_window;
long active, delta;
sample_window = READ_ONCE(calc_load_update);
if (time_before(jiffies, sample_window + 10))
return;
delta = calc_load_nohz_fold();
if (delta)
atomic_long_add(delta, &calc_load_tasks);
// 現在アクティブなプロセス数を算出
active = atomic_long_read(&calc_load_tasks);
active = active > 0 ? active * FIXED_1 : 0;
// それぞれ 1, 5, 15分間の平均値を格納
// 実際の計算はcalc_load 関数内で行っている
avenrun[0] = calc_load(avenrun[0], EXP_1, active);
avenrun[1] = calc_load(avenrun[1], EXP_5, active);
avenrun[2] = calc_load(avenrun[2], EXP_15, active);
WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);
calc_global_nohz();
}
/*
* @param load 前回の Load Average
* @param exp 平均をとる期間ごとに定められた定数
* @param active 現在の Active なプロセス数
*/
static unsigned long
calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
load *= exp;
load += active * (FIXED_1 - exp);
return load >> FSHIFT;
}
```
## まとめ
## 参考サイト
[マルチコア時代のロードアベレージの見方](http://d.hatena.ne.jp/naoya/20070518/1179492085)
[Load Average はどうやって算出されているのか](https://www.techscore.com/blog/2017/12/08/how_is_load_average_calculated/)
[LoadAverage(ロードアベレージ)について](https://qiita.com/toshihirock/items/c121400dd58c5d77f85a)
[torvalds/linux](https://github.com/torvalds/linux)