独自のIOスレッドプールを作成する場合を除いて、glibcの実装は許容できるソリューションです。実際には、完全にユーザーランドで実行されるものに対しては驚くほどうまく機能します。
私の経験では、カーネルの実装はバッファリングされたIOではまったく機能しません(他の人が反対のことを言うのを見たことがありますが!)。DMAを介して大量のデータを読み取りたい場合はこれで問題ありませんが、もちろん、バッファキャッシュを利用する場合は、かなりの時間がかかります。
また、カーネルAIO呼び出しが実際にブロックされる可能性があることにも注意してください。サイズに制限のあるコマンドバッファがあり、大きな読み取りはいくつかの小さな読み取りに分割されます。キューがいっぱいになると、非同期コマンドが同期的に実行されます。サプライズ。私は1、2年前にこの問題に遭遇し、説明を見つけることができませんでした。周りに尋ねると、「もちろん、それがどのように機能するか」という答えが得られました。
私が理解したことから、バッファリングされたaioをサポートすることへの「公式の」関心も、何年にもわたっていくつかの実用的なソリューションが利用可能であるように見えますが、それほど大きくはありません。私が読んだ議論のいくつかは、「とにかくバッファを使いたくない」、「誰もそれを必要としない」、「ほとんどの人はまだepollを使っていない」というものでした。だから、まあ...まあ。
完了した非同期操作によってシグナルを受け取ることができることはepoll
、最近まで別の問題でしたが、それまでの間、これはを介して非常にうまく機能しeventfd
ます。
glibcの実装は、実際には内でオンデマンドでスレッドを生成する__aio_enqueue_request
ことに注意してください。スレッドの生成はそれほど高価ではなくなったので、おそらく大したことではありませんが、注意する必要があります。非同期操作の開始についての理解が「すぐに戻る」である場合、最初にいくつかのスレッドを生成する可能性があるため、その仮定は正しくない可能性があります。
編集:
補足として、Windowsでは、非同期操作をキューに入れるという「すぐに戻る」という仮定が当てはまらない、glibcAIO実装の状況と非常によく似た状況が存在します。
読み取りたいすべてのデータがバッファキャッシュにある場合、Windowsは代わりに要求を同期的に実行することを決定します、とにかくすぐに終了するので。これは十分に文書化されており、確かに素晴らしいと思います。コピーする数メガバイトがある場合、または別のスレッドにページフォールトがある場合、またはIOを同時に実行する場合(したがって、ロックを競合する場合)を除いて、「すぐに」は驚くほど長い時間になる可能性があります。 -5ミリ秒。これはほとんどの状況で問題ありませんが、たとえば、16.66msのフレーム時間の制約の下では、ランダムな時間に5msの間ブロックするリスクを冒したくないでしょう。したがって、「非同期はブロックしないので、レンダリングスレッドから非同期IOを実行できる」という素朴な仮定には欠陥があります。