「OZV勉強会LT」「Linux」niceコマンドで知るプロセスと優先順位

オズビジョン社内勉強会LT資料です。

---

## Niceとは

変更したスケジューリング優先度でプログラムを実行する
man page : https://linuxjm.osdn.jp/html/GNU_coreutils/man1/nice.1.html

```
nice [OPTION] [COMMAND [ARG]...]  

-n, --adjustment=N
優先度に整数値 N を加える (デフォルト: 10)

--help
この使い方を表示して終了する

--version
バージョン情報を表示して終了する 
```

---

## Niceの使い方

```
# -n [niceness value] オプション必須
# nicenessの範囲は, 19 ~ -20 ※nicenessが低いほど、優先順位は高くなる

nice -n /something/default_nicevalue_is_10
nice -n 0 /batch_sh/something.sh #niceness valueを0
nice -n 5 zgrep "something text" very_huge_data.log.gz
nice -n 10 mysqldump -u user -p DBNAME TABLE_NAME > OUTPUT_FILE
nice -n -10 /something/this_is_high_priority_execution
```

---

## プロセスの優先順位確認

---

### psで確認
```
# PRI, NIを確認

[vagrant@comics ~]$ ps l
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1000 22121 22120  20   0 124924  4256 -      Ss   pts/0      0:00 -bash
0  1000 22647 22121  20   0 160236  2204 -      R+   pts/0      0:00 ps l
```

---

### topで確認
```
# PR, NIで確認

[vagrant@comics ~]$ top
top - 18:36:27 up  2:22,  1 user,  load average: 1.15, 0.77, 0.66
Tasks: 167 total,   3 running,  90 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.4 us,  2.9 sy,  0.0 ni, 94.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1009004 total,   263660 free,   337808 used,   407536 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   508032 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
22255 apache    20   0  523200  30656  11248 R  20.6  3.0   0:00.69 httpd
 3018 mysql     20   0 2050332 121596  19976 S   0.7 12.1   0:11.54 mysqld
    8 root      20   0       0      0      0 R   0.3  0.0   0:03.04 rcu_sched
 3217 root      20   0  236900  22764   4652 S   0.3  2.3   0:02.13 fluentd
22867 vagrant   20   0  171112   4592   3896 R   0.3  0.5   0:02.46 top
```

---

### PRとNI
---

#### NIとは
プロセスのniceness値、優先順位補正値（ユーザースペース設定値）

#### PR(PRI)とは
カーネルススケジューラーで参考する、実際のプロセス優先順位
一般プロセスのPRの計算式 : 20 - NI

※ niceを指定せず実行する一般プロセスのPRは20になる。
※ リアルタイムプロセス(rt)の説明はここではしない。

---

## プログラムとプロセス

---

### プログラムとは？
コンピューターが解釈し実行できる命令語コードの集合。
一般的にはファイル形式で保存されている状態。

### プロセスとは？
プログラムに対し、実行命令がくだされたタイミングから、生成される資源。

一般的人はプロセス資源はメモリーにロードされ、
OSのプロセススケジューリングのコントロールの制御下で、
上位のメモリと演算装置によって命令が処理される。

---

### プログラムとプロセスの関係
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436887/c8f443d5-0185-4e13-7ee9-2cd7bd372d5a.png)


---

## プロセス優先順位の必要性

---

### なぜ、OSは多数のプログラムを実行・処理できるのか？
基本的に、1CPU(1CORE)は１回1個の命令しか処理できない。(1回 = 1hz, 3Ghz = 1秒で30億回、命令を処理できる)

この制約条件下で、プログラムが同時に処理されていると感じる理由は

- OSの「プロセススケジューラー」のプロセスコントロール
- プロセスのステータス変化(Life Cycle)

の概念があって、成り立っている。

---

### プロセススケジューリング
大体のOSは、複数のプロセスを処理するためにいろんなアルゴリズムを採用しているが、基本的にTime Sharingの概念を使っている。複数のプロセスが、優先順位によって、自分の順番で処理可能な時間が設定される。

わかりやすい例が、round-robinアルゴリズム
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436887/8acbf505-34f9-728d-9531-ccea6c2164f2.png)


---


### プロセスの状態変化(Life Cycle)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436887/d22ebc35-c65d-52f0-b769-f2f34e2267a4.png)


- creation : あらたらプロセスの生成
- dispatch : OSスケジューラーがCPUの計算時間を割り当て、処理を実行させること。Running状態に移行
- timeout : 割り当てられた計算時間の切れ。リソースを返却し、Ready状態に移行
- blocking/unblocking : プロセスのIO作業発生時にIO処理を待つためblock状態で待機、プロセサで制御


---

### 優先順位とスケジューリングがなかったらどうなるか？
複数のプロセスが、同じ時間の割当で、プロセスが増えるほど、全体の処理時間が遅延される。
問題は、重要なプロセス・システムプロセスにも影響が響きシステムの制御命令系が働かなくなること。

---

## 実務では

---

### OS環境で何かを実行することは、プロセスになるということを意識する
サーバーで何らかのコマンド、プログラムを実行するということは、コンピューターの限られたリソースの一部を時間という形で占有することを意味する。

一般プロセスの優先順位は指定しない限りは、同じ比率のリソースを当て貼れられるので、プロセスが増えれば増えるほど他のプロセスの処理時間にも影響を及ぼすことになる。

niceは、この時間占有程度を指定し、プロセスごとの処理優先順位を制限的にコントロールできる。

```
# ありえる？
本番ウェブサーバーで、バッチ処理を追加したら、ウェブサイト全体の応答速度が落ちた。
>>> APACHE(prefork setting)の場合、1リクエストがプロセスになるので、当然プロセス優先順位の影響を受ける。
>>> バッチ処理が、時間に重要な処理じゃなければ、優先順位を下げて実行するようにする（サーバーを分けるまでではない場合）

本番バッチサーバーで、何らかのバッチを手動実行したら、
何時まで絶対周り終わらなきゃいけない、他のバッチの処理時間が遅延された。
>>> 手動で実行するバッチは特別な理由がない場合は、適切に優先順位を下げて実行する
```

---

### niceの活用例
前提としては、リアルタイムの必要性が低く、重い処理を前提としている。


#### 本番のバッチサーバーで、手動バッチ実行作業が必要
```sh
nice -n 10 /batch_sh/huge_time_and_low_priority.sh
```

#### mysqldumpで、大容量データのダンプ
```sh
nice -n 10 mysqldump -u xxxx -p DBNAME > all_db_dump.sql
```

---

#### 本番のウェブサーバー、本番ログサーバーのgrep
```sh
nice -n 10 zgrep -E `^\d+$` 1GB_FILE.log.gz

# zgrepと正規表現の処理はCPUに負荷がすごくかかる作業
```

---

#### phpの中でのシステくコールによるバイナリ実行
```php5
exec('nice -n 10 /something/command', $result, $ret);

# バッチ処理の中でのシステムコールか、非同期処理の中で必要な場合
# システムコールを使うのに対しては推奨しないため、参考までに見ておくこと
```

## 結論

- APACHEも、バッチも、Shell Commandも、何ら化を実行したら、それはプロセス。
- プロセスは、限られた時間内で処理・待機を繰り返す。
- プロセスが増えるほど、全体プロセスの待機時間が伸び、処理自体が遅延される。
- `nice`コマンドで、プロセスに当てる時間を制限的にコントロールできる
- 実行するプログラムの優先度・サーバーへの影響度を考え、`nice`を活用してみよう

※PS : プログラムの軽量化も大事。

---

## 補足:  `renice`
既存のプロセスのnicenessを変更