UbuntuとLinux I/Oスケジューラー(後編)
「UbuntuとLinux I/Oスケジューラー(前編)」の続きです。I/Oスケジューラーはストレージアクセスへのリクエスト(要求)を、データの論理アドレスに基づき線形順序でリクエストを並び替えたり、リクエストを一纏めにグルーピングすることで、スループットの改善を試みます。
これにより全体のスループット向上に期待できますが、リクエストの中に長い間待たされてしまうリクエストが発生する可能性があり、遅延の問題に繋がります。
異なる手法で実装された様々なI/Oスケジューラーが存在しますが、それぞれ特性が異なり一長一短があります。
これらのI/Oスケジューラーを大別すると、「シングルキューI/Oスケジューラー(非マルチキューI/Oスケジューラー)」と「マルチキューI/Oスケジューラー」に分類されます。
シングルキューI/Oスケジューラー
1.Deadline
「Deadline」は、他のI/Oスケジューラーで見られるような一部リクエストの長い遅延の発生を抑えることができます。「Deadline」ではI/Oリクエストに3つのキューを使用します。
- Sorted queue(読み書きリクエスト/セクター番号で並び替え)
- Read queue(読み取りリクエスト/期限で並び替え)
- Write queue(書き込みリクエスト/期限で並び替え)
リクエストは「Sorted queue」から発行されます。
「Deadline」は「Read queue」及び「Write queue」の先頭にあるリクエストが期限切れになっていないかチェックし、期限切れのリクエストを優先的に処理します。
この時「Write queue」よりも「Read queue」が優先されます。
読み取りリクエストには500msの期限が設定され、書き込みリクエストには5秒の期限が設定されます。
このI/Oスケジューラーに関する設定は、以下を参照してください。
2.CFQ(Completely Fair Queueing)
「CFQ」は、プロセスごとに同期I/Oリクエストを保持する「Sorted queue」を持ちます。各キューの均衡を図るためタイムスライスが割り当てられ、ディスクへのアクセスが行われます。
各キューに割り当てられるタイムスライスの長さや、キューから発行可能なリクエストの数は、「ionice」の優先度が考慮されます。
またすべてのプロセスの非同期I/Oリクエストを優先度毎に保持する少数の「Queue」を持ちます。
ただしタイムスライスが期限切れになる前に余計な待機時間が発生する可能性があります。
このI/Oスケジューラーに関する設定は、以下を参照してください。
3.Noop(No-operation)
「Noop」は、I/Oリクエストのマージは行いますが、I/Oリクエストの並び替えを行いません。セクター番号による並び替えが性能に影響を与えないストレージ向けのI/Oスケジューラーです。
FlashストレージやSSD、RAMディスクなどランダムアクセスが高速なストレージを利用している場合に有用なI/Oスケジューラーです。
またI/Oリクエストを並び替える高度なストレージコントローラーを利用している場合にも有用です。
マルチキューI/Oスケジューラー
マルチキューI/Oスケジューラーは、マルチキューデバイス向けに設計されているI/Oスケジューラーです。I/Oリクエストを複数のキューに割り当て(マップ/マッピング)、複数のCPUに横断的に分散させたカーネルスレッドにより処理が行われます。
1.BFQ(Budget Fair Queueing)
「BFQ」は「CFQ」を拡張・改良した実装であり、特にI/Oが遅いストレージでより良い応答性を提供するように設計されています。「BFQ」は複雑なI/Oスケジューラーであり、他のI/Oスケジューラーに比べて各処理毎に高い処理コストがかかります。
そのため低速なCPUや高速なI/Oを提供するストレージには向いていません。
リクエストの均衡は、要求されたセクター数及びタイムスライスよりもヒューリスティクスに基づき処理されます。
このI/Oスケジューラーに関する設定は、以下を参照してください。
2.Kyber
「Kyber」は、高速なマルチキューデバイス向けに設計され、他のI/Oスケジューラーに比べてシンプルな実装になっています。「Kyber」は以下の2種類のキューを持ちます。
- 同期リクエストキュー(ブロックの読み込みなど)
- 非同期リクエストキュー(書き込みなど)
キューに送られるリクエスト操作の数には、厳格な制限があります。
理論的にはこの制限により、発行されるリクエストの待ち時間を制限することができます。
そのため優先度の高いリクエストを早く完了させることができます。
このI/Oスケジューラーに関する設定は、以下を参照してください。
3.None
「None」は、マルチキュー向けNo-operation I/Oスケジューラーです。リクエストの並び替えを行わず、処理コストは最低限で済みます。
「NVME」のような高速なランダムアクセスを提供するストレージに有用です。
4.MQ Deadline(mq-deadline)
「MQ Deadline」は、「Deadline」をマルチキュー向けに適合させたI/Oスケジューラーです。このI/Oスケジューラーに関する設定は、以下を参照してください。
Ubuntuで利用可能なI/Oスケジューラー
「Ubuntu」では「Ubuntu」のバージョンにより、デフォルトで利用可能なI/Oスケジューラーが異なります。1.Ubuntu 19.10(Linux kernel 4.20)より前
「Ubuntu 19.10(Linux kernel 4.20)」より前のバージョンでは、マルチキューI/Oスケジューラーはデフォルトで有効になっていません。シングルキューI/Oスケジューラーはデフォルトで有効になっており、以下のI/Oスケジューラーを利用できます。
- Deadline
- CFQ
- Noop
2.Ubuntu 19.10(Linux kernel 4.20)以降
「Ubuntu 19.10(Linux kernel 4.20)」以降のバージョンでは、デフォルトでマルチキューI/Oスケジューラーが有効になっており、以下のI/Oスケジューラーを利用できます。- BFQ
- Kyber
- None
- MQ Deadline
注意と捕捉
「Linux kernel 4.20」は現在開発中のバージョンであり、2018年12月16日に「Linux kernel 4.20 RC7」がリリースされています。「Ubuntu 19.04」は2019年4月にリリース予定であり、「Ubuntu 19.04」のリリースに「Linux kernel 4.20」が間に合います。
上記ではドキュメントに従い「Ubuntu 19.10」と表記していますが、「Ubuntu 19.04」のことを指している可能性もあります。
I/Oスケジューラーの利用と選択
マルチキューI/Oスケジューラーの無効化
カーネルパラメーターにより、マルチキューI/Oスケジューラーを無効化しシングルキューI/Oスケジューラーに切り替えることも可能です。例えばSCSIデバイスで「blk-mq(Multi-Queue Block IO Queueing Mechanism)」を無効化するには、以下の作業を行います。
- 「/etc/default/grub」を開く
- 「GRUB_CMDLINE_LINUX_DEFAULT」に「scsi_mod.use_blk_mq=0」を追記する
- 「sudo update-grub」を実行してPCを再起動する
I/Oスケジューラーを変更する
I/Oスケジューラーの変更は、ブロックデバイスごとに適用されます。シングルキューデバイスの場合
「/dev/sda」がシングルキューデバイスだとします。以下のコマンドを実行すると「/dev/sda」で利用可能なI/Oスケジューラーを調べることができます。
cat /sys/block/sda/queue/scheduler
「/dev/sda」のI/Oスケジューラーを「Deadline」に変更するには、以下のコマンドを実行します。
echo "deadline" | sudo tee /sys/block/sda/queue/scheduler
マルチキューデバイスの場合
「/dev/sda」がマルチキューデバイスだとします。以下のコマンドを実行すると「/dev/sda」で利用可能なI/Oスケジューラーを調べることができます。
cat /sys/block/sda/queue/scheduler
[mq-deadline] none
[mq-deadline] none
I/Oスケジューラーを「Kyber」に変更するには、まず以下のコマンドを実行し「Kyber」モジュールを読み込みます。
sudo modprobe kyber-iosched
利用可能なI/Oスケジューラーに「Kyber」が追加されています。
cat /sys/block/sda/queue/scheduler
[mq-deadline] kyber none
[mq-deadline] kyber none
そしてI/Oスケジューラーを「Kyber」に変更するには、以下のコマンドを実行します。
echo "kyber" | sudo tee /sys/block/sda/queue/scheduler
最善のI/Oスケジューラーを選ぶために
最善のI/Oスケジューラーは、環境により異なります。最善のI/Oスケジューラーを選ぶためには、ストレージの特性やストレージの使われ方を想定したテストが必要です。
テストの一例とテスト環境
テストの一例の紹介です。本テストのテスト結果は、25種の異なるI/Oパターンを組み合わせ、以下のファイルシステムで「fio」を使用しテストが行われています。
- ext2
- ext3
- ext4
- xfs
- btrfs
また「Linux kernel 4.19」上でテストされています。
SSD
SSDを対象にしたテスト結果です。I/Oパターン | 第1候補 | 第2候補 | 非推奨 |
---|---|---|---|
ランダムI/O | CFQ/Deadline | ー | BFQ |
シーケンシャルI/O | Deadline | Noop | BFQ |
データベースI/O | Deadline | Noop | BFQ |
一般的なI/O | Deadline | Noop | BFQ |
捕捉
「Deadline」は、マルチキューデバイスでは「MQ Deadline」を使用しています。「Noop」は、マルチキューデバイスでは「None」を使用しています。
総評
高速なSSD/NVMEデバイスでは、「CFQ」/「Deadline」/「MQ Deadline」/「Kyber」間のスループットの差は小さな差しかなく、有意な差は見られませんでした。このテスト結果からお勧めのI/Oスケジューラーは、CPUの使用量を抑える「Noop」もしくは「None」でしょう。
HDD
HDDを対象にしたテスト結果です。I/Oパターン | 第1候補 | 第2候補 | 非推奨 |
---|---|---|---|
ランダムI/O | Deadline | BFQ/CFQ | BFQ/Noop |
シーケンシャルI/O | Deadline | BFQ | Noop |
データベースI/O | Deadline | ー | BFQ/Noop |
一般的なI/O | Deadline | BFQ | Noop |
捕捉
「Deadline」は、マルチキューデバイスでは「MQ Deadline」を使用しています。「Noop」は、マルチキューデバイスでは「None」を使用しています。
総評
HDDでは「Noop」及び「None」の使用は推奨しません。ブロックアドレスに基づきI/Oリクエストの並び替え(最適化)を行うことで、ヘッドのシーク時間(ヘッドのシーク待ち)を減らすことができ、リクエストの処理にかかる時間を減らすことができます。
しかし「Noop」及び「None」は、I/Oリクエストの並び替えを行いません。