Linux:昨今のI/Oスケジューラ事情 2020

Linux
この記事は約6分で読めます。

※当サイトは広告収入で運営されているため、広告が表示される場合があります。

まえがき

HDDやSSDはシステムの中でもボトルネックとなる一番データの転送速度が遅い記憶媒体だ。 オペレーティング・システムには記憶媒体による遅延を減らすためキャッシュを利用するなど I/Oアクセスを最小限に留める工夫が施されている。そんな中でもI/OスケジューラはI/Oリクエストの処理順を入れ替えたりリクエストを一つにまとめたりすることにより応答速度やスループットを向上させる機能だ。ディスク・スケジューリングとも呼ばれることがある。

数年前まではLinuxカーネルは cfq noop deadline と言ったI/Oスケジューラを搭載していたが、昨今のスケジューラはだいぶ変わっているようだ。

Linuxカーネル ver 3.13 からCPUの多コア化、SSDやPCIeなどの高速な記憶媒体の普及に対応するために旧来の単一キュー処理からマルチキュー処理をする Blk-mq(Multi-Queue Block IO Queueing Mechanism) という新しいAPIが採用された。これにより従来よりも大量のI/O処理を一度に行えるようになり、 150,000 IOPS 以上のストレージに対応した。I/Oスケジューラもこれに応じて刷新された。

それでは昨今のLinuxの各ディストリビューションがどのような I/Oスケジューラを採用しているのか見ていこう。

メジャーディストリビューションのスケジューラ

以下のコマンドでシステムに搭載されている I/O スケジューラを調べることができる。

$ cat /sys/block/sd*/queue/scheduler
  • Debian 10.4 のI/Oスケジューラ
[mq-deadline] none
  • Arch Linux 2020.6 のI/Oスケジューラ
mq-deadline kyber [bfq] none
  • Fedora 32 のI/Oスケジューラ
mq-deadline kyber [bfq] none

当たり前だがLinuxのカーネルバージョンによって使えるスケジューラは決まってくる。Arch LinuxやFedoraといったLinuxカーネルの更新が早いディストリビューションではDebianにはないスケジューラが新たに追加されているのことがわかる。

つぎは先程表示されたI/Oスケジューラである MQ-DeadlineKyberBFQNone についてみていこう。

MQ-deadline I/O スケジューラ

deadline をマルチキュー向けに作り直した I/O スケジューラ。文字通りデッドライン(時間制限)を設けリクエストの処理開始時間を保証するのが目的。特定の処理がスタックすることを回避できる。単純なスケジューラだが設計思想的にはスループットよりもレイテンシーの解消を優先しているので高速なドライブだけでなく低速なドライブにも適している。

Kyber I/O スケジューラ

Kyber は Facebook によって開発されたスケジューラ。Kyber スケジューラは読み込み開始までの待ち時間(ナノ秒)read_lat_nsecと同期までの時間(ナノ秒)write_lat_nsecの2つのパラメータのみで構成されているシンプルなスケジューラ。Kyber は設定されたレイテンシーに間に合うよう各リクエストの調整を行う。単純なスケジューラゆえ高速なデバイスに向いている。

BFQ I/O スケジューラ

BFQ (Budget Fair Queueing)は CFQ (Completely Fair Queueing) をマルチキュー機構向けに改良したスケジューラ。BFQ はデフォルト設定だとスループットよりもデバイスによるレイテンシーをできるだけ少なくするようリクエストの整理を行う。音声や動画を扱うアプリケーションに向いているとされている。

CPUの処理速度の低さに比例して IOPS に制限がかかるので高スループットを実現したい場合はそれなりに高性能なCPUが必要になる。逆にストレージの転送速度があまりよくないデバイスでのマルチタスキングに有効だろう。複雑なスケジューラのため物理的に回転するドライブや低速な SSD に適している。

None (Noop)

None は名前の通りスケジューリングを全く行なわず、そのままリクエストをデバイスに送る。リクエストの調整を全く行わないので CPU に対する負荷はほとんどない。NVMe プロトコルのSSDなど、ランダムアクセスが高速な記憶媒体に向いている。

逆に低速なドライブで I/Oスケジューラを無効にすると高負荷状態で特定の I/O リクエストがスタックし、システムがフリーズしてしまう可能性もある。高速な SSD ドライブが主流になりつつあるがシステムの安定性を考慮して MQ-Deadline や BFQ を採用してるディストリビューションが多いのはこのためであろう。

廃止されたスケジューラ

CFQ (Completely Fair Queuing)

CFQ の頭字語で Linux カーネルのデフォルトスケジューラ。I/O 優先度をサポートし、その優先度に応じて処理を行う。スケジューラが多数の内部キューを維持しシステム上で動作するプロセス間での I/O リクエストを公平に処理する。システムへの負荷は他のスケジューラに比べ大きい。待ち時間に限界値がある。

Deadline

正確には Deadline は廃止されていないが現在はマルチキューに対応した MQ-Deadline が主流となっている。記憶メディアのディスク上でディスクヘッドの位置から一番近い I/O リクエストから処理していく。ディスクヘッドから遠い I/O 要求は後回しにされるが待ち時間に上限が設けられており、タイムリミットに達した要求が出た際にはそちらを優先する。

どのスケジューラが良いのか

どのスケジューラが良いのかは自身の使っているシステムとアプリケーションによる。

HDD には BFQ を選ぶのが無難だ。

M.2 NVMe などの高速ドライブでは None (Noop)が最もドライブの性能を引き出せるが、SATA 接続の SSD などは処理がもたつく可能性がある。安定性を重視するならば MQ-Deadline が良いだろう。

Linux 5.6 I/O Scheduler Benchmarks: None, Kyber, BFQ, MQ-Deadline - Phoronix

スケジューラの変更方法

sda ドライブを BFQ I/O スケジューラに変更するには以下のようにコマンドを使用すれば良い。

# echo bfq > /sys/block/sda/queue/scheduler

SSD と HDD が混在するシステムではそれぞれ違うスケジューラを割り当てたい。こんなときに udev でルールを設定することでシステムに自動的に設定させることができる。

# sudoedit /etc/udev/rules.d/60-ioschedulers.rules
# 無回転デバイス用のスケジューラ設定
ACTION=="add|change", KERNEL=="sd[a-z]|mmcblk[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
# 回転デバイス用のスケジューラ設定
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"

Photo by Marc PEZIN on Unsplash

最後に

スケジューラはSSDの登場によって大きく変わった。さらにCPUの多コア化により処理自体は単純に見えるがアルゴリズムは少々複雑化している傾向がある。これからI/Oスケジューラがどのように進化していくのか楽しみだ。

おわり

コメント

タイトルとURLをコピーしました