(2020) 5.1 以上の Linux カーネルを使用している場合は、io_uring
を使用できます ファイルのような I/O 用のインターフェイスを提供し、優れた非同期操作を取得します。
既存の libaio
との比較 /KAIO インターフェイス、io_uring
次の利点があります:
- (直接 I/O を実行するときだけでなく) バッファ I/O を実行するときに非同期動作を保持します
- 使いやすい (特に
liburing
を使用する場合) ヘルパー ライブラリ) - オプションでポーリング方式で動作できます (ただし、このモードを有効にするには、より高い権限が必要です)
- I/O ごとの簿記スペースのオーバーヘッドが少ない
- ユーザー空間/カーネル syscall モードの切り替えが少ないため、CPU オーバーヘッドが削減されます (スペクター/メルトダウンの軽減策の影響により、最近では大きな問題になっています)
- ファイル記述子とバッファを事前登録して、マッピング/アンマッピング時間を節約できます
- より高速 (より高い総スループットを達成でき、I/O のレイテンシーがより低くなります)
- 「リンク モード」は、I/O 間の依存関係を表現できます (>=5.3 カーネル)
- ソケットベースの I/O (
recvmsg()
) で動作可能 /sendmsg()
>=5.3 からサポートされています。io_uring.c の git history でサポートという言葉に言及しているメッセージを参照してください) - キューに入れられた I/O のキャンセル試行をサポート (>=5.5)
- その I/O を常に要求できます インライン送信パスがブロックをトリガーしたときに、I/O を非同期コンテキストにパントするだけにフォールバックするデフォルトではなく、非同期コンテキストから実行する (>=5.6 カーネル)
read
以降の非同期操作の実行に対するサポートの拡大 /write
(例:fsync
(>=5.1)、fallocate
(>=5.6)、splice
(>=5.7) 以上)- 発展の勢い
- 星が完全に揃わないたびにブロックされることはありません
glibc の POSIX AIO と比較すると、io_uring
次の利点があります:
- かなり より高速で効率的 (上記のオーバーヘッド削減の利点は、ここでもさらに適用されます)
- インターフェイスはカーネルでサポートされており、ユーザー空間のスレッド プールを使用しません
- バッファリングされた I/O を実行するときに作成されるデータのコピーが少なくなります
- 合図と格闘しない
- Glibc の POSIX AIO は、
io_uring
に対して、1 つのファイル記述子で複数の I/O を飛行中に持つことはできません。 間違いなくできます!
Efficient IO with io_uring ドキュメントは、io_uring
に関してさらに詳しく説明しています。 のメリットと使い方。 What's new with io_uring ドキュメントでは、io_uring
に追加された新機能について説明しています io_uringLWN の急速な成長の記事では、5.1 から 5.5 のカーネルのそれぞれでどの機能が利用可能であったかを説明し、5.6 でどうなるかを概観しています (LWN の io_uring 記事のリストも参照してください)。 io_uring
による Faster IO through io_uring Kernel Recipes ビデオ プレゼンテーション (スライド) は 2019 年後半から、What's new with io_uring Kernel Recipes ビデオ プレゼンテーション (スライド) は 2022 年半ばからです。 著者のイェンス・アクスボー。最後に、io_uring チュートリアルの主が io_uring
を紹介します
io_uring
コミュニティには io_uring メーリング リストからアクセスでき、io_uring メーリング リストのアーカイブは 2021 年初頭の毎日のトラフィックを示しています。
Re "recv()
の意味で部分 I/O をサポート vs read()
":io_uring
を自動的に再試行するパッチが 5.3 カーネルに入りました 短い読み取りと、REQ_F_NOWAIT
を設定していないリクエストで「通常の」ファイルを操作するときに、短い読み取りのみを自動的に処理するように動作を調整する 5.4 カーネルにさらにコミットが入りました。 フラグ (REQ_F_NOWAIT
をリクエストできるようです) IOCB_NOWAIT
経由 または O_NONBLOCK
でファイルを開く )。したがって、recv()
を取得できます style- io_uring
からの「短い」I/O 動作
io_uring
を使用したソフトウェア/プロジェクト
インターフェイスは新しいものですが (最初の化身は 2019 年 5 月に登場しました)、一部のオープンソース ソフトウェアは io_uring
を使用しています。 "野生":
- fio (これも Jens Axboe によって作成されています) には io_uring ioengine バックエンドがあります (実際には、2019 年 2 月の fio-3.13 で導入されました!)。 2 人の Intel エンジニアによる「新しい Linux カーネル I/O インターフェイス SNIA を使用したストレージ パフォーマンスの向上に関するプレゼンテーション」(スライド) では、1 つのワークロードで IOPS を 2 倍にし、キューの深さ 1 で平均レイテンシを半分以下にすることができたと述べています。
io_uring
を比較するときの別のワークロード ioengine をlibaio
に Optane デバイス上の ioengine。 - SPDK プロジェクトは、v19.04 リリースで、ブロック デバイス アクセスに io_uring (!) を使用するためのサポートを追加しました (ただし、これは、ベンチマーク以外で通常 SPDK を使用するバックエンドではありません)。最近では、v20.04 でソケットを使用するためのサポートも追加されたようです...
- Ceph は、15.1.0 リリースの一部である io_uring バックエンドを 2019 年 12 月にコミットしました。コミットの作成者は、一部の io_uring バックエンドが libaio バックエンドと比べて (IOPS、帯域幅、レイテンシーに関して) ワークロードに応じて勝敗があることを示す github コメントを投稿しました。
- RocksDB が
io_uring
をコミットしました 2019 年 12 月の MultiRead のバックエンドであり、6.7.3 リリースの一部でした。 Jens はio_uring
を述べています 待ち時間を劇的に短縮するのに役立ちました。 - libev は最初の
io_uring
で 4.31 をリリースしました 2019 年 12 月のバックエンド。著者の元のポイントのいくつかは新しいカーネルで対処されましたが、執筆時点 (2021 年半ば) で、libev の著者はio_uring
についていくつかの選択の言葉を持っています。 の成熟度を見極め、さらなる改善を実施する前に様子見のアプローチを取っています。 - QEMU は 2020 年 1 月に io_uring バックエンドをコミットし、QEMU 5.0 リリースの一部でした。 「QEMU の io_uring:Linux の高性能ディスク IO」PDF プレゼンテーションで、Julia Suvorova が
io_uring
を示しています。threads
を上回るバックエンド とaio
ランダムな 16K ブロックの 1 つのワークロードのバックエンド。 - Samba は
io_uring
をマージしました 2020 年 2 月の VFS バックエンドで、Samba 4.12 リリースの一部でした。 「Linux io_uring VFS バックエンド」。 Samba メーリング リスト スレッド、Stefan Metzmacher (コミット作成者) はio_uring
と述べています モジュールは、合成テストで (特定されていないバックエンドと比較して) 約 19% 多いスループットをプッシュすることができました。変更の背後にある動機の一部については、Stefan による「Async VFS Future」PDF プレゼンテーションを読むこともできます。 - Facebook の実験的な C++ libunifex はそれを使用します (ただし、5.6+ カーネルも必要です)
- Rust の人々は
io_uring
を作るためのラッパーを書いています。 純粋な錆にアクセスしやすくなります。 rio は少し話題になったライブラリの 1 つであり、著者は、スレッドにラップされた同期呼び出しを使用する場合と比較して、より高いスループットを達成したと述べています。著者は FOSDEM 2020 で彼のデータベースとライブラリについてプレゼンテーションを行い、io_uring
の美徳を称賛するセクションが含まれていました。 . - Rust ライブラリ Glommio は
io_uring
のみを使用します .著者 (Glauber Costa) は、Modern storage is pretty fast というドキュメントを公開しました。 Glommio を慎重に調整することで、通常の 2.5 倍以上のパフォーマンスを得ることができることを示しているのは、悪い API です (non-io_uring
) ) Optane デバイスでシーケンシャル I/O を実行するときのシステムコール。 - Gluster は 2020 年 10 月に io_uring posix xlator をマージし、Gluster 9.0 リリースの一部でした。コミットの作成者は、パフォーマンスが「通常の pwrite/pread syscall よりも悪くない」と述べています。
io_uring
を使用して調査するソフトウェア
- PostgreSQL 開発者の Andres Freund は、
io_uring
の原動力の 1 人です。 改善 (例:ファイルシステムの inode 競合を減らすための回避策)。 「Asynchronous IO for PostgreSQL」というプレゼンテーションがあります (ビデオは 5 分のマークまで壊れていることに注意してください) (PDF) は、PostgreSQL の変更の必要性を動機付け、いくつかの実験結果を示しています。彼はオプションのio_uring
を手に入れたいという希望を表明しました PostgreSQL 14 へのサポートを開始し、カーネル レベルに至るまで、何が機能し、何が機能しないかを鋭く認識しているようです。 2020 年 12 月、Andres は彼の PostgreSQLio_uring
についてさらに議論します。 「Blocking I/O, async I/O and io_uring」pgsql-hackers メーリング リスト スレッドで作業し、進行中の作業については https://github.com/anarazel/postgres/tree/aio で確認できると述べています。 /li> - Netty プロジェクトには、
io_uring
で動作するインキュベーター リポジトリがあります。 5.9 カーネルを必要とするサポート - libuv には、
io_uring
を追加するプル リクエストがあります。 サポートされていますが、プロジェクトへの進行が遅い - SwiftNIO が
io_uring
を追加しました 2020 年 4 月のイベンティング (syscall ではない) のサポートと Linux:完全な io_uring I/O の問題は、それをさらに統合する計画の概要を示しています - Tokio Rust プロジェクトは概念実証 tokio-uring を開発しました
io_uring
の Linux ディストリビューションのサポート
- (2020 年後半) Ubuntu 18.04 の最新の HWE 有効化カーネルは 5.4 なので
io_uring
syscall を使用できます。このディストリビューションはliburing
をあらかじめパッケージ化していません ヘルパー ライブラリですが、自分で構築することもできます - Ubuntu 20.04 の初期カーネルは 5.4 なので
io_uring
syscall を使用できます。上記のように、ディストリビューションはliburing
を事前にパッケージ化していません . - Fedora 32 の初期カーネルは 5.6 および パッケージ化された
liburing
があります だからio_uring
使用可能です。 - SLES 15 SP2 には 5.3 カーネルがあるため、
io_uring
syscall を使用できます。このディストリビューションはliburing
をあらかじめパッケージ化していません ヘルパー ライブラリですが、自分で構築することもできます - (2021 年半ば) RHEL 8 のデフォルト カーネルはしない
io_uring
をサポート (この回答の以前のバージョンでは、誤ってそうだと言っていました)。 「進行中」の Add io_uring サポート Red Hat ナレッジベース記事 (コンテンツはサブスクライバー ペイウォールの背後にあります) があります。 - (2022 年半ば) RHEL 9 のデフォルト カーネルはしない
io_uring
をサポート .カーネルは十分に新しい (5.14) ですが、io_uring
をサポートしています は明示的に無効になっています。
できれば io_uring
Linux の非同期ファイルのような I/O ストーリーの先駆けとなるでしょう。
(この回答に信憑性の薄いベニアを追加するために、過去のある時点で、Jens Axboe (Linux カーネル ブロック レイヤーのメンテナーおよび io_uring
の発明者) ) この回答は賛成する価値があると思いました :-)
Peter Teoh によって間接的に指摘された本当の答えは、io_setup() と io_submit() に基づいています。効率的な実装です。本当の答えは次のとおりです。
io_submit(2)
io_setup(2)
io_cancel(2)
io_destroy(2)
io_getevents(2)
2012 年 8 月付けのマニュアル ページによると、この実装は glibc ユーザー空間エミュレーションを置き換えることができる点まではまだ成熟していません。
http://man7.org/linux/man-pages/man7/aio.7.html
<ブロック引用>この実装は、カーネル システム コールを使用して POSIXAIO 実装を完全に再実装できるほど成熟していません。
そのため、私が見つけた最新のカーネル ドキュメントによると、Linux にはまだ成熟したカーネル ベースの非同期 I/O モデルがありません。そして、文書化されたモデルが実際に成熟していると仮定すると、recv() と read() の意味での部分的な I/O はまだサポートされていません。