I/OスケジューラとブロックI/O層
HDD時代の常識がSSDで覆る理由を内部から理解。エレベータからblk-mqまで、ディスク要求の並べ替えがどう速さを生むかが一本でつながります。
- 1.ブロックI/O層は上位のread/writeをbioに変え、I/Oスケジューラがマージと並べ替えでデバイスへ渡す。回転HDDではシーク削減が最大の目的だった。
- 2.エレベータ(C-LOOK)はヘッドの一方向掃引でシーク距離を最小化。CFQやDeadlineはこれに公平性や遅延上限を足した拡張。
- 3.SSDとNVMeの並列性に単一キュー+ロックは足かせとなり、CPUごとにキューを分けるblk-mqへ移行。後継はmq-deadline・Kyber・BFQ。
ブロックI/O層という中間管理職
アプリの read/write はシステムコールを経てカーネルに入り、ページキャッシュを通り抜けると最終的にブロックデバイスへの要求になります。この変換と整流を担うのがブロックI/O層です。ファイルの論理オフセットはファイルシステムが物理ブロック番号(LBA)へ翻訳し、その結果が bio という構造体に詰められます。bio は「どのセクタへ、どのメモリページの内容を、読むか書くか」を表すI/Oの最小単位です。
ブロックI/O層の核心は、この bio をそのままデバイスへ流さない点にあります。間にI/Oスケジューラ(エレベータ)を挟み、要求を**マージ(併合)し並べ替え(リオーダ)**してからデバイスへ渡す。なぜそんな手間をかけるのか——その答えは回転ディスクの物理にあります。
なぜ並べ替えが効くのか:シークの物理
HDDは磁気ヘッドを目的トラックへ動かし(シーク)、目的セクタが回ってくるのを待ちます(回転待ち)。シークは機械動作なのでミリ秒単位で、1回のI/Oの大半を占める固定費です。要求がLBA順にバラバラだと、ヘッドは内周と外周を往復し続けて時間を浪費します。
ここで並べ替えが効きます。届いた要求をLBA順にソートして近い順に処理すれば、ヘッドの移動距離を劇的に減らせる。さらに隣接・連続するセクタへの要求は1つの大きな要求にマージでき、コマンド発行のオーバーヘッドも下がります。これがI/Oスケジューラの存在理由です。
新しい bio が既存要求の末尾に続くならバックマージ、先頭に付くならフロントマージです。実装上バックマージのほうが頻度が高く、ハッシュで高速に隣接要求を探します。マージは要求数そのものを減らすため、並べ替え以上に効くことも多いです。
エレベータアルゴリズム
並べ替えの古典がエレベータアルゴリズムです。ビルのエレベータが上昇中は上の階だけ拾い、最上階で折り返すのと同じく、ヘッドを一方向に掃引しながら通り道の要求を順に処理します。
- SCAN:端まで進んでから逆方向へ折り返す。両端が有利になりがち。
- C-SCAN:端まで行ったら並べ替えず一気に逆端へ戻り、再び同方向へ。位置による不公平を均す。
- C-LOOK:最遠の要求まで行ったら(端ではなく)戻る。実装上の定番。
ヘッド位置 → 現在地
LBA軸: |--A----C--[H]--E------G--| 要求 A,C,E,G
C-LOOK掃引: [H]→E→G (右端の要求まで)
戻って →A→C (ラップして再掃引)
純粋なエレベータの弱点は**飢餓(スターベーション)**です。遠いLBAへの1件は、近場に要求が来続ける限り永久に後回しになりかねません。この公平性の欠如を埋めるために、後続のスケジューラが生まれました。
旧世代(シングルキュー)の三役
blk-mq以前のLinuxは、デバイスごとに1本の要求キューを1つのロックで守る設計(レガシーブロック層)でした。そこに載った代表的スケジューラが次の3つです。
| 方式 | 中心アイデア | 向く用途 | 弱点 |
|---|---|---|---|
| Noop | マージのみ、並べ替えなし | SSDや賢いRAID(順序は下位に任せる) | 回転HDDではシーク増 |
| Deadline | 読み/書きに期限を付け、期限超過要求を割り込ませる | 遅延を抑えたいDB等 | 厳密な公平配分は弱い |
| CFQ | プロセス(cgroup)ごとにキューを持ち時間スライスで公平配分 | 対話・多プロセス混在の汎用デスクトップ | オーバーヘッド大・SSDで非効率 |
Deadline は要求をLBAソート済みキューと期限(FIFO)キューの両方に登録します。通常はソート順に処理してシークを減らしますが、ある要求が期限(既定で読み500ms・書き5s)を超えたら、その要求を最優先で割り込ませる。これでエレベータの飢餓を構造的に防ぎます。読みを書きより短い期限にするのは、読みが同期的でアプリを待たせるからです。
CFQ(Completely Fair Queuing) はCPUスケジューラのCFSと同じ「公平」の発想をI/Oへ持ち込み、プロセスごとにキューを与えタイムスライスを回します。アイドリング(同じプロセスの次要求を少し待つ)でシーク局所性も稼ぎますが、その待ちと多数キューの管理が高IOPSデバイスでは純粋な足かせになりました。
CFQは局所性を期待して数ミリ秒「待つ」ことがあります。シークの無いSSDでは待つ理由がなく、ただスループットを削るだけ。SSD普及がCFQ退役の決定打になりました。
SSD・NVMeが壊した前提とblk-mq
SSDにはヘッドが無く、シークも回転待ちもありません。並べ替えで得られる利得は激減し、代わりに内部の多数チャネルを同時に叩く並列性が性能の源になります。NVMeに至っては最大65535本のハードウェアキュー、各深さ65536を規格で許します。
この世界で旧来の「1キュー+1ロック」は致命的でした。全CPUコアが1本のロックを奪い合い、せっかくの並列デバイスへ要求を直列にしか注げない。ロック競合がデバイス性能の前にCPUを飽和させます。
そこで導入されたのが blk-mq(マルチキューブロック層) です。キューを2段に分けます。
- ソフトウェアキュー:CPU(コア)ごとに1本。要求はまず自コアのキューに入るので、コア間のロック競合が原理的に消える。
- ハードウェアディスパッチキュー:デバイスが持つ実キューに対応。ソフトウェアキューの要求をここへ流し込みデバイスへ発行する。
CPU0 CPU1 CPU2 CPU3 ← ソフトウェアキュー(コア毎・競合なし)
\ | | /
[ hctx 0 ] [ hctx 1 ] ← ハードウェアディスパッチキュー
| |
NVMe HW-Q0 NVMe HW-Q1 ← デバイスの実キュー
コアとハードウェアキューを対応づければ、割り込みの完了処理も発行したコアで受けられ、キャッシュ局所性が効きます(割り込みとI/O参照)。Linuxは5.0でレガシー層を撤廃し、blk-mqへ一本化しました。
blk-mq時代のスケジューラ
blk-mqでは「並べ替えはもう不要」かというと、そうでもありません。遅延の保証やプロセス間の公平性はSSDでも価値があるため、軽量な新スケジューラが用意されています。
| 方式 | 正体 | 狙い | コスト感 |
|---|---|---|---|
| none | スケジューラを挟まない | NVMe等、並列が極めて高いデバイス | 最小 |
| mq-deadline | Deadlineのblk-mq版 | 期限保証+軽い並べ替え | 低 |
| kyber | 完了遅延を測り発行数を絞る適応制御 | 高IOPSで遅延を一定以下に保つ | 低 |
| bfq | CFQ後継の予算公平スケジューラ | 対話応答・公平性が要るHDD/SATA SSD | 高 |
Kyber は発想が独特です。読み・書きそれぞれの完了遅延(レイテンシ)を実測し、目標値を超えそうならデバイスへ同時に出す要求数(トークン)を絞る。並べ替えで最適化するのではなく、詰め込みすぎを抑えて遅延の裾を切るフィードバック制御で、NVMeのような高速デバイスに合います。
BFQ(Budget Fair Queueing) はCFQの正統後継で、時間スライスの代わりにセクタ予算でプロセスへI/Oを配分します。対話プロセスを検知して優先するなど応答性に強い反面、計算コストが高く、最高IOPSを狙うNVMeでは none に劣ることがあります。用途で選ぶのが鉄則です。
「SSDでI/Oスケジューラはなぜ none/mq-deadline が推奨されるか」を説明できるかが分かれ目。要点は2つ——(1) シークが無いので並べ替えの利得が小さい、(2) デバイス自身が高い並列性を持つため、ソフト側で並べ替え・アイドリングするほどかえってスループットを削る。一方、遅延保証や公平性が要る場面では mq-deadline / BFQ が依然有効、という両面を押さえます。
まとめ
ブロックI/O層は read/write を bio に変え、I/Oスケジューラがマージと並べ替えでデバイスへ橋渡しします。回転HDDではシーク削減が至上命題で、エレベータ(C-LOOK)が一方向掃引で移動を最小化、Deadlineが期限で飢餓を防ぎ、CFQがプロセス公平を実現しました。だがSSD/NVMeはシークを消し並列性を主役にし、単一キュー+ロックを時代遅れにします。blk-mqはソフト/ハードの2段キューでコア間競合を断ち、後継のmq-deadline・Kyber・BFQが「遅延保証」と「公平性」を低コストで提供。土台にあるシステムコールのコストや割り込みの完了通知まで遡ると、ストレージ性能の理由が一本の線でつながります。
OS Article
I/OスケジューラとブロックI/O層を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
I/Oスケジューラ
比較で見る軸
難易度: advanced / カテゴリ: OS / タグ数: 6
導入後に効く点
エレベータ(C-LOOK)はヘッドの一方向掃引でシーク距離を最小化。CFQやDeadlineはこれに公平性や遅延上限を足した拡張。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- OS
- タグ数
- 6
判断チェックリスト
- 自社の用途が「I/Oスケジューラ / blk-mq」に近いか確認する。
- 強みである「ブロックI/O層は上位のread/writeをbioに変え、I/Oスケジューラがマージと並べ替えでデバイスへ渡す。回転HDDではシーク削減が最大の目的だった。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。