システム負荷切り分け自分メモ

# 概要
CentOSでシステムのボトルネックを調査する時の問題切り分け方法の自分メモ。

## 前提
* カーネルモードでCPUが使われるのは、`割り込み`、`システムコール`、`カーネルスレッド`

## ロードアベレージとは
* CPUの実行権限が与えられているのを待っているタスク
* ディスクI/Oが完了するのを待っているタスクの

**２つの状態のプロセスの数**


# 切り分けフロー
- LA高いか？
  * 低い 
      - ネットワークなどがボトルネックになっているかも。**muninなど、NWに関するグラフを見ると帯域が圧迫しているなどありえる**
      - OSの設定などがボトルネック。カーネルのsynパケットの受付数が低いなど。
      - **アプリケーション、OSのログ、各種ログを見ることが大事** 

↓
LA高い場合

- vmstatで負荷の特徴把握
↓

- CPU負荷 or IO負荷 どちらか
  * cpu負荷: us列, sy列 が高い
  * IO負荷: b列をみる。IO列は低くてもIOが高い場合がるので注意
  
↓

+ CPU負荷の場合
    + システム空間での負荷(system列多い)
        - 割り込み調査
        - システムコール調査
        - カーネルスレッド調査
    + ユーザー空間での負荷(user列多い)
        - アプリケーション調査
+ IO負荷の場合
    + スワップ
        - メモリ沢山使用しているプロセスを調査
    + IO量
        - iostatでボトルネックがディスクなのか、ディスクより上のシステムコール層、VFS層、ファイルシステム層なのかを調査

## 詳細
## LAが高いか？
* `uptime`,`sar -q 1`などでLAを把握

## vmstat、その前に
* `mpstat -P ALL 1`などで各コアでの状況を確認したほうがよい。コアで分散すれば解決するような問題もある。
* システムログも大事(dmesg | tail)
    - oomkillerやパケットのエラーなどでている場合がある様子。エラーは使用率や飽和などを端的に表しているのでやはりログのエラーは大事。

## vmstatで負荷の特徴を把握する
* `vmstat -S m 1`

```sh
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0     17   5064    275    204    0    0     3   154   11   16  0  1 96  3  0 
 0  0     17   5064    275    204    0    0     0   580 1255  329  1  2 87 10  0
```

## 特徴無し
* muninなども含めてシステムに異常がない場合は、監視の閾値上げても良いかも


## waが高い
* IO負荷調査へ

## syとwaが高い
* IO負荷調査へ

## syだけ高い場合(システム空間での負荷)
- `top`などでどのプロセスがCPUを使っているか特定しておく
- waが小さくてもIO負荷ありえるので、IO負荷もありうる。[IO待ちメモ](http://qiita.com/saikoro-steak/items/244362bcceec4df19343)
    - システムの他の箇所(前提より、`割り込み`、`システムコール`、`カーネルスレッド`)のどれかでCPU沢山使っている
        - 割り込み調査
            - `vmstat`のcs,inが多い
            - `systemtap`、`perf`で割り込みの種類を特定する。その割り込み毎に対応する。
        - システムコール調査
            - `strace -c -tttT -p` してシステムコールのレイテンシ、頻度を計測。怪しいシステムコールを把握する。
            - システムコールの先を`systemtap`、`perf`で調査。関数まで特定する。カーネルソース読んで静的解析。
        - カーネルスレッド調査
            - `systemtap`,`perf`で調査。関数まで特定する。カーネルソース読んで静的解析。

## us高い(ユーザー空間での負荷)
* プロセスのログをみる。apacheならアクセスログなど、変なIPなどないかなどなど。
* `top`などでどのプロセスがCPUを使っているか特定してして`psatck`を何回か打ってユーザースタックを確認することでアプリケーションがどの処理で何をしているのかを把握する。ただアプリケーションのシンボル情報がない場合が多いはずなので関数名は16進数表示になっているかも。カーネルの関数やなぜか共有ライブラリの関数はわかるはずなのでそこからなんとかする


# IO負荷高い場合
## スワップを疑う
* `vmstatの`swpd、`free`でスワップの状況を把握
* メモリを消費しているプロセス特定
    - `ps aux --sort -rss`

## IO量が多いかどうか
* `iostat`で調査
    - IOPS(r/s + w/s)が増え、await(1回のI/Oに要する時間)が増える、(avgqu-sz)キューも増えている場合
        + IOが増えた原因はなにかを調査する必要あり
            * `iotop`でプロセス特定
            * アクセスログ、重いクエリ、などなどアプリの観点で調査
    -  平均 I/O サイズ(avgrq-sz)が変わらないのにサービスタイム、1回のI/Oに要する時間 (ミリ秒)(svctm)が大きくなった場合
        +   I/O性能が劣化しており、ストレージに問題がありそう
    - ストレージがボトルネックになっていない場合
        + それより上のシステムコール層、VFS層、ファイルシステム層を調査
            * `strace -cttT -p`でIOに関するシステムコールのレイテンシを測定。時間が通常よりかかっていればディスクより上層が怪しい。レイテンシが小さいのであればストレージもそれより上層も怪しくない。
            * ここでも深く調べるには`systemtap`,`perf`。そう、カーネルソースまで追ってボトルネックになっている関数を特定する。

iostatのカラムの見方

http://d.hatena.ne.jp/yohei-a/20110711/1310396665

```
r/s: 秒間の読み込み回数
w/s: 秒間の書き込み回数
avgrq-sz: 平均 I/O サイズ
avgqu-sz: 平均待ち行列長
await: レスポンスタイム。I/O を実施していない待ち時間を含む。
svctm: サービスタイム。1回のI/Oに要する時間 (ミリ秒)。
%util: 使用率（ビジー率）
```


# メモ
## IOのレスポンスが悪いかどうか
* iotopなどで怪しいプロセスを発見、`strace -cttT -p` してIO関連システムコールのレイテンシを計測する。
* レイテンシが大きかったらiostatでどこがボトルネックになっているのはディスクなのか、それより上位なのか切り分ける。最初からiostatで切り分ければよいのかも

## VFS層、ブロック層
```
システムコール
　　↓
---------------------------------------------
(VFSレイヤー)
　VFS
　　↓
ファイルシステム ←　→ ディスクキャッシュ
---------------------------------------------
  　↓
---------------------------------------------
(ブロックレイヤー)
IOスケジューラ　→　デバイスドライバ
---------------------------------------------
　　　　　　　　　　　　　↓
　　　　　　　　ディスクコントローラ
　　　　　　　　　　　　　↓
　　　　　　　　　　 物理ディスク
```



# まとめ
* システム空間で負荷がある場合、深く調べるには上記で度々できているsystemtap、perfなどのLinuxツールでボトルネックになっている関数まで特定するしかなさそう。そしてソースを呼んで静的に解析。対策実施。
* 自分で根本原因まで特定しようとしたいならば、最後はカーネルソースに辿り着くことがありそう。そして、システムの状況とコードを結びつけてなんとか原因を推定してチューニングを実施する。自分でここまでできるのがオープンソースのよいところ。
* [perf使ってみた](http://qiita.com/saikoro-steak/items/bf066241eeef1141ef5f)

# 参考
* https://yakst.com/ja/posts/3601?platform=hootsuite
* http://d.hatena.ne.jp/yohei-a/20110711/1310396665
* http://d.hatena.ne.jp/yohei-a/20121030/1351561743