Linuxサーバーの最適化: vmstatとiostatを活用した性能分析と対処法

# Linuxサーバーの最適化: vmstatとiostatを活用した性能分析と対処法

![title](https://raw.githubusercontent.com/legitwhiz/legitwhiz.github.io/master/technology_memo/images/1000008106.jpg)

## 0.目的

インフラ開発者として、必須な性能分析を身につけることを目的としています。
カーネルパラメータをチューニングをする際に性能分析を前提とし、分析結果からチューニングしていきますが、具体的な指標というものが少ないので参考になれば幸いです。

基本的なvmstatの使い方については、ちょっとググればいくらでも出てくるので割愛します。
「[Linuxカーネルパラメータのチューニング＆設計](https://qiita.com/legitwhiz/items/359d58e8ec6fb54d1a7b)」でロードアベレージが高い状態にある場合、次のアクションとしてCPU使用率の確認が必要となりますので、vmstatの結果分析および対処法について深堀していきます。

よって、vmstatの結果分析と対処法を理解すると性能試験を実施した際のその対処法とカーネルパラメータによるチューニングする対象が理解できるかと思います。

## 1.パフォーマンスに関して注目すべき項目とそのフロー

### 1.1 vmstatによる性能解析フロー

```mermaid
flowchart TB

Node1[vmstat]
Node2{ld<10}
Node3{so>10}
Node4[メモリのスケールアップ<span style="color: red; ">①</span>]
Node5{us>70}
Node6{wa>70}
Node7{r>4}
Node8{b>4}
Node9{bi,bo>3000}
Node10[HDD I/O分散化<span style="color: red; ">⑤</span>]
Node11[システムコールなど<span style="color: red; ">④</span>]
Node12{コアごとのus>70}
Node13[CPUアップグレード<span style="color: red; ">②</span>]
Node14[HDD I/O分散化<span style="color: red; ">③</span>]
Node15[CPUアップグレード<span style="color: red; ">⑥</span>]
Node16{in>200}
Node17[CPUスケールアップ<span style="color: red; ">⑧</span>]
Node18[HDD I/O分散化<span style="color: red; ">⑨</span>]
Node19[HDD交換<span style="color: red; ">⑦</span>]
Node20[iostat]

Node1 --> Node2 -- No --> Node3 -- No --> Node12 -- No --> Node14
Node2 -- Yes --> Node5
Node3 -- Yes --> Node4
Node5 -- No --> Node6
Node5 -- Yes --> Node7
Node7 -- No --> Node8
Node7 -- Yes --> Node9
Node6 -- No --> Node11
Node6 -- Yes --> Node10
Node12 -- Yes --> Node13
Node8 -- No --> Node15
Node8 -- Yes --> Node16
Node9 -- No --> Node17
Node9 -- Yes --> Node18
Node16 --No --> Node20
Node16 --Yes --> Node19

```

### 1.2.vmstatの状態とその対処法

#### ① so>10[メモリのスケールアップ]
スワップアウトが発生しているため、システムの応答に遅延が発生しています。スワップアウトは物理メモリが不足しているため、メモリのスケールアップをしましょう。

### ② コア１つだけがus>70[CPUアップグレード]
アプリケーションがマルチコアとなっておらず、１つのコアで処理しているため、実行キューに入っているプロセス数は高騰せず、usのみ高騰します。そのため、アプリケーションをマルチスレッドで動作するよう改修するか、CPUのアップグレードをする必要があります。

#### ③ id<10,コア毎のus<70[ディスクI/O分散化]
ディスク I/Oがボトルネックになっている可能性があります。
ディスク I/Oの分散化もしくはサーバのスケールアウトを検討してください。

### ④ us<70,b<4,[fork関数多用アプリケーションの調査]
この状況の場合は、vmstatでcpu syが70%以上となっているはずです。
アプリケーション要因以外のCPU使用率がボトルネックだが、アプリケーションで fork,vfork,clone などのシステムコールが多発しています。プログラムが原因もあるため注意が必要です。(そもそもシステム起因でCPUが高騰する場合はパッチ適用などの対応が必要)

fork数は、vmstatの-fオプションで確認することができます。
fork関数を多用しているアプリケーションやミドルウェアを見直ししてください。

また、NFSやsambaなどのファイル共有システムでもアクセスが多発すると同様な事象になりえます。
ファイル共有を分散するなどの検討を行ってください。

#### ⑤ sy>70,wa>70[HDD I/O分散化]
ディスクのI/O待ちにより、システムの応答速度に遅延が発生しています。
I/O待ちを発生しているプロセスを特定し、改善させるかディスクI/Oを高速化するかの対応を検討してください。

#### ⑥ us>70,r<4,b<4[CPUアップグレード]
CPUリソースが不足しています。
CPUのアップグレード、スケールアウトを検討してください。

#### ⑦ r<4,b<4,in<200[HDD交換]
HDDの初期不良、HDD内部の磁性体の経年劣化、磁気ヘッドの破損によりHDDのバッドセクターおよびバッドブロックが発生している可能性が高いです。
バッドセクター、バッドブロックを回復するコマンド、ツールも存在しますが、そもそもハードウェアの劣化が原因なので物理的に交換をお勧めします。

バッドセクターが発生している場合(critical medium error)は、dmesgコマンドにて確認することができます。

```:例
[ 2909.160643] sd 4:0:0:0: [sdc] UNKNOWN(0x2003) Result: hostbyte=0x00 driverbyte=0x08
[ 2909.160659] sd 4:0:0:0: [sdc] Sense Key : 0x3 [current]
[ 2909.160664] sd 4:0:0:0: [sdc] ASC=0x11 ASCQ=0x0
[ 2909.160670] sd 4:0:0:0: [sdc] CDB: opcode=0x28 28 00 38 a3 0c 20 00 00 20 00
[ 2909.160675] blk_update_request: critical medium error, dev sdc, sector 950209568
```


#### ⑧ us>70,r>4,b>4,bi,bo<3000[アプリケーション改修、CPUスケールアップ]
アプリケーションが過度に使用しています。
対象プロセスを特定し、ミドルウェアならサポートに相談し、アプリケーションの場合は、担当チームに相談する。ミドルウェア、アプリケーションで対応不可であればCPUスケールアップを検討してください。

#### ⑨ us>70,bi,bo>3000[HDD I/O分散化]
ファイルコピーやDBなどI/Oが過度に多い状態です。
I/Oを分散、高速化するかサーバのスケールアウトを検討してください。
 
### 1.3. iostatによる性能解析フロー
iostatには-xオプションを付与して実行してください。

```mermaid
flowchart TB

Node1[lostat]
Node2{%utl>80}
Node3{w/s>r/s}
Node4[ディスクI/O分散化<span style="color: red; ">①</span>]
Node5[ディスク・キャッシュの使用<span style="color: red; ">②</span>]
Node6[ネットワークの調査<span style="color: red; ">③</span>]

Node1 --> Node2 -- No --> Node3 -- No --> Node6
Node2 -- Yes --> Node4
Node3 -- Yes --> Node5

```


### 1.4. iostatの状態とその対処法

#### ① %utl>80[ディスクI/O分散化]
ファイルコピーやDBなどI/Oが過度に多い状態です。
I/Oを分散、高速化するかサーバのスケールアウトを検討してください。

#### ② %utl<80,w/s>r/s[ディスク・キャッシュの使用]
ディスク・キャッシュが不足しています。カーネルパラメータの設定変更を検討してください。
現状の設定は以下で確認できます。

**バックグラウンドでライトバックを行うキャッシュサイズの閾値 (物理メモリに占める割合[%])**
```
$ sudo cat /proc/sys/vm/dirty_background_ratio
5
```

**フォアグラウンドでライトバックを行うキャッシュサイズの閾値 (物理メモリに占める割合[%])**
```
$ sudo cat /proc/sys/vm/dirty_ratio
10
```

**ライトバックされるまでのキャッシュの保持時間**
```
$ sudo cat /proc/sys/vm/dirty_expire_centisecs
3000
```

**キャッシュの経過時間を監視する間隔**
```
$ sudo cat /proc/sys/vm/dirty_writeback_centisecs
500
```

#### ③ %utl<80,w/s<r/s[ネットワークの調査]
ネットワークがボトルネックになっています。
`netstat -e -a -i -n` によりネットワークインターフェイス毎の ネットワーク使用状況が確認できます。
インターフェイス起動後からの累積値で表されるため、定期的に採取して差分を採る必要があります。



# おすすめ記事

## カーネルパラメータチューニング
https://qiita.com/legitwhiz/items/359d58e8ec6fb54d1a7b

## ネットワークチューニング
https://qiita.com/legitwhiz/items/63659e3e267899dea56c