vmspliceは_あまりにも_速い
- 一部のプログラムは、データをパイプ経由でより高速に移動させるために
vmsplice というシステムコールを使用する
vmsplice を使わない場合、Linuxパイプが予想より遅いことを発見した
- モールス符号を高速にエンコード/デコードするプログラムを書いており、そのためにパイプを使っている
理想的な環境でのデータ書き込み
- 以下のプログラムは、システムコールなしでデータをコピーする
- AVX-512 を使用して 167 GB/s の速度で実行される
- AVX-512 を無効にして AVX2 および SSE2 でテストした場合でも、同じ速度(167 GB/s)を記録した
- ベクトル化が使われている限り、167 GB/s の速度を達成できる
実際にパイプへデータを書き込む
- パイプにデータを書き込むプログラムを書いて測定したところ、17 GB/s の速度を記録した
- これはバッファに書き込む場合より 10 倍遅い
- プロファイリングの結果、ほとんどの時間が
write 呼び出しに費やされていた
pipe_write 関数でメモリページを割り当てるのに多くの時間がかかっている
- データコピー自体は CPU 時間の 20% しか占めていないが、それでも
__memset_avx512_unaligned_erms より 2 倍遅い
vmsplice の助け
vmsplice は、ユーザー空間からカーネルへバッファをコピーせずに移動させる
vmsplice を使うと 210 GB/s の速度を達成できる
vmsplice は write システムコールの高コストな部分を回避する
まとめ
- パイプへの書き込みは、生のメモリへの書き込みより 10 倍遅い
- これはバッファをロックするコストと、SIMD コンテキストの保存・復元コストによるものだ
splice と vmsplice はこれらのコストを避け、データを効率的に移動させる
GN⁺の要約
- この記事は、
vmsplice を使って Linux パイプの性能を最大化する方法を説明している
vmsplice はデータをカーネル空間へコピーせず直接移動させることで、性能を大きく向上させる
- モールス符号のエンコード/デコードのような高速データ処理プログラムに有用だ
- 似た機能を持つ他のプロジェクトとしては、
splice や sendfile などがある
1件のコメント
Hacker Newsの意見
JMPがRETに置き換えられないのは、CONFIG_RETHUNK オプションのためRETがJMP __x86_return_thunkに置き換えられた結果を確認できる関数の先頭と末尾にある NOP 命令は、ftrace がトレース命令を挿入できるようにしている
あるユーザーのサイドプロジェクトでは、ファイルディスクリプタ向けのリングバッファを提供するシステムコールを提案している
Linux のパイプを「遅い」と呼ぶのは、Toyota Corolla を「遅い」と呼ぶのと同じ
現代の CPU では、
rep movsbは最速のベクトル化バージョンと同等に速いcopy_user_enhanced_fast_stringがそれを示唆しているAVX512 は消費電力が大きく、CPU の周波数スケーリングを引き起こす
Hacker News の「hug of death」を再び体験している
io_uring を使ったバージョンを見るのは興味深そう
ブログの読み込み時間が約 20 秒かかるというのは大胆な主張
ほぼあらゆる形の IPC は「遅い」
もともと splice がなぜあれほど遅いのか理解できなかった