io_uring vs libaio 性能比較:Linuxカーネル別ベンチマークと謎の30%性能劣化の原因【IOMMU落とし穴】

元記事を読む
キュレーターコメント

「io_uringが速い」は知っていても「どのカーネルでどれだけ変わるか」の数字を持っている人は少ない。IOMUUによる隠れた性能劣化という実話が特に刺さる、NVMe・データベース系エンジニア必読のレポート。

概要

Linuxで非同期I/Oを使っているエンジニアなら「io_uringはlibaioより速い」という話は耳にしたことがあるだろう。しかし「カーネルバージョンごとにどれだけ変わるのか」という具体的な数字はほとんど公開されていない。分散SQLデータベースYDBの開発チームが、まさにその疑問に正面から答えるベンチマークを実施し、その過程でIntel IOMUUが引き起こす予想外の30%性能劣化という罠を発見した話が非常に興味深い。

なぜカーネルバージョン間の比較が重要なのか

YDBはプロダクション環境でLinux 5.4・5.15・6.6を運用しており、6.12への移行を検討していた。「カーネルを上げたら非同期I/Oの性能はどう変わるのか?」という実用的な疑問が出発点だ。ベンチマークツールにはfio 3.41を使用し、以下の構成で計測している。

  • ハードウェア: Intel Xeon Gold 6338(32コア×2)、512GB RAM、NVMe Intel P4610 3.2TB
  • カーネル: 5.4 / 5.15 / 6.6 / 6.18 / 7.0-rc3
  • ワークロード: ランダム4Kライト(iodepth=16)
  • エンジン: libaio / io_uring / io_uring+IOPOLL / io_uring+SQPOLL / io_uring+IOPOLL+SQPOLL
sudo fio --name=write_latency_test --filename=<dev> --filesize=2500G \
  --time_based --ramp_time=10s --runtime=1m \
  --rw=randwrite --direct=1 --bs=4K \
  --iodepth=16 --iodepth_batch_submit=1 --iodepth_batch_complete_max=1 \
  --ioengine=io_uring --sqthread_poll --hipri=1 \
  --lat_percentiles=1 --percentile_list=10:50:90:95:99:99.9 \
  --output-format=json

ベンチマーク結果:io_uringの圧勝と進化

結果は明快だった。主な発見をまとめる。

  • io_uringはlibaioの最大2倍高速(SQPOLL+IOPOLLモードで顕著)
  • 最高性能のio_uring構成は、古いカーネルより新しいカーネルで1.4倍速い
  • io_uringは単にlibaioに勝つだけでなく、カーネルが新しくなるほど性能が向上し続けている
  • SQPOLL(Submission Queueのポーリングをカーネルスレッドが担当)とIOPOLL(完了をポーリングで待つ)の組み合わせが最も強力

io_uringのモード別に簡単に整理すると:

モード特徴
通常モードシステムコールで送信・割り込みで完了通知
IOPOLL完了をポーリングで確認(低レイテンシ)
SQPOLLカーネルスレッドがSQを監視(CPUコア占有と引き換えに超低レイテンシ)
IOPOLL+SQPOLL両方の組み合わせ(最高性能・最高CPU消費)

謎の30%性能劣化と真犯人:Intel IOMMU

興味深いのはここからだ。チームは当初、5.4→5.15でlibaioとio_uring(非SQPOLLモード)が約30%遅くなるという謎の現象に直面した。「カーネルリグレッションでは?」と疑い調査したところ、真の原因はIntel IOMUUがカーネル5.15以降でデフォルト有効になったことだった。

IOMMU(Input/Output Memory Management Unit)はDMA攻撃等からの保護やデバイスの分離に使われるセキュリティ機能だが、NVMeのような高速I/Oデバイスではアドレス変換のオーバーヘッドが無視できない。ブートパラメータに intel_iommu=off を追加したところ、性能劣化が解消した。

もちろんIOMMUを無効にするのはトレードオフで、セキュリティ要件次第だ。しかし「カーネルを上げたら遅くなった」という事象の本当の原因を追うことで、こうした隠れたデフォルト変更を発見できるという教訓は大きい。

まとめ:io_uring移行を検討しているなら今がベストタイミング

このベンチマークから得られる実践的な示唆は明確だ。

  • io_uringへの移行は性能面で明確なメリットがある。特に高iodepthのワークロードで2倍の差が出る
  • カーネル6.6以降を使えば、さらに1.4倍の上乗せが期待できる
  • SQPOLL+IOPOLLモードは最高性能だが、専用CPUコアを消費することを念頭に置く
  • カーネルアップグレード後に性能が落ちたら、IOMMMUなどデフォルト設定の変更を真っ先に疑う
  • blkdiscard でNVMeデバイスをリセットしてからベンチマークを取る習慣も重要(フラッシュストレージの状態が結果に影響する)

YDBチームの調査は、単なるio_uring礼賛ではなく「なぜ速くなったのか」「なぜ遅くなったのか」を地道に追った誠実なエンジニアリングブログだ。NVMeを使ったデータベースやストレージシステムを開発しているエンジニアには、元記事のグラフや詳細なfio設定も含めてぜひ一読を勧めたい。