Convivaは、Rust製分析エンジンでメモリーマップド・ファイルアクセスをio_uringに置き換える試みの詳細を明らかにし、メジャーページフォルトを大幅に削減したにもかかわらず、最初の書き換えでは60%遅くなったと報告した。この結果は、非同期ダイレクトI/Oを検討しているエンジニアリングチームへの警告となる。1つのボトルネックを取り除いても、最初の代替設計が高速になるとは限らない。

同社のエンジンは、ローカルのNVMeドライブに保存された大容量のArrow IPCファイルを処理する。標準的なクエリは8つのファイルにまたがる複数のカラムを読み取り、1日分のデータにつき約13GBにアクセスする。システムはDataFusion、Arrow、Rust、Rayon、Tokioを使用し、192個のCPUコアと約750GBのメモリーを搭載したサーバー上で稼働する。ディスク上とメモリー上の表現が一致し、ゼロコピーのランダムアクセスが可能になるため、当初、メモリーマッピングはArrowのレイアウトによく適合していた。

同時アクセスが発生する本番環境の負荷下で問題が表面化した。Convivaは、長時間実行されるクエリがホストのページキャッシュを満たし、プロセス同士が共有カーネル状態を奪い合う事態を引き起こしていることを突き止めた。1台のマシン上で行った対照比較では、14日分のクエリにおいて1つのPodが4つのPodを上回り、その優位性は最大で41%に達し、95パーセンタイルでは20%を超えた。性能プロファイリングでは、カーネルロックの競合、ページの排出と再挿入の繰り返し、毎秒数百万回のマイナーフォルトが確認された。

この負荷によって、負荷の高いテストでは毎秒200万回を超えるコンテキストスイッチも発生した。これは、キャッシュがウォームな状態での実行時における約1万4,000回と対照的だった。Convivaは、32台のドライブ構成でfioテストでは毎秒約21GBに達するハードウェア上で、mmapのピークスループットが毎秒3.44GBだったと測定した。同社は、生のドライブ性能ではなく、ページキャッシュの挙動とカーネルの競合がクエリ性能を制限していると結論付けた。

そこでエンジニアは、io_uring、O_DIRECT、RustネイティブのCompioライブラリを中心とする代替方式を構築した。この設計はページキャッシュを迂回し、Arrowの各カラム読み取りに対してfutureを投入するもので、テスト用ワークロードでは40件のカラム操作を同時に発行した。macOSはio_uringを提供していないものの、同OS上での初期開発はバッチ処理とコンパイルの検証に役立った。

この変更により、想定通りページフォルトは減少した。初期テストではメジャーフォルトが約70分の1に減った。それにもかかわらず総実行時間は増加し、最初の実装は大幅に遅くなった。Convivaによると、当初の設計ではio_uringに期待していた複数の利点を実現できず、効果的な実装を構築するには、I/O、スケジューリング、デコードをより慎重に連携させる必要があった。

この結果は、io_uringが本質的にmmapより遅いことを示すものではない。本番環境の性能が、アクセスパターン全体とソフトウェア設計に左右されることを示している。Convivaの測定結果も、同社固有のファイルサイズ、同時実行性、カーネル、ハードウェアに当てはまるものだ。それでも、公開された調査は、実態を反映した負荷の下でベンチマークを行い、低レベルのI/Oプリミティブを自動的な性能向上策ではなくツールとして扱うべきだという有用な注意喚起となっている。