1. ホーム
  2. c++

[解決済み】mmap()とブロックの読み込みの比較

2022-04-08 04:31:29

質問

私は、潜在的に100GB以上の大きさのファイルを処理するプログラムに取り組んでいます。ファイルは可変長レコードのセットを含んでいます。私は最初の実装を稼働させ、現在はパフォーマンスを向上させるために、特に入力ファイルが何度もスキャンされるため、より効率的にI/Oを行うことに注目しています。

を使用する際の経験則はありますか? mmap() と、C++のブロック読み込みの fstream ライブラリですか?私がやりたいのは、ディスクから大きなブロックをバッファに読み込んで、バッファから完全なレコードを処理し、さらに読み込むということです。

は、その mmap() のコードは、非常に面倒なことになる可能性があります。 mmap のブロックはページサイズの境界線に置かれる必要があり(私の理解では)、レコードはページ境界を越えて置かれる可能性があります。このため fstream の場合、ページサイズの境界にあるブロックを読むことに制限されないので、レコードの先頭にシークして、再び読み始めることができるのです。

この2つのオプションは、実際に完全な実装を書き上げることなく、どのように決定すればよいのでしょうか?何か経験則(例. mmap() の方が2倍速い)、あるいは簡単なテストができますか?

どのように解決するのですか?

Linuxでのmmap/readのパフォーマンスについて最終的な情報を得ようとしていたところ、素敵な投稿に出会いました( リンク )のLinuxカーネルメーリングリストに掲載されました。 2000年のものなので、その後カーネルのIOや仮想メモリには多くの改良が加えられていますが、その理由がうまく説明されています。 mmap または read の方が速いかもしれないし、遅いかもしれません。

  • への呼び出しは mmap よりもオーバーヘッドが大きくなります。 read (ちょうど epoll よりもオーバーヘッドがあります。 poll よりも多くのオーバーヘッドを持つ read ). 仮想メモリマッピングの変更は、異なるプロセス間の切り替えが高価であるのと同じ理由で、一部のプロセッサーでは非常に高価な操作となります。
  • IOシステムはすでにディスクキャッシュを利用できるので、ファイルを読めば、どのような方法を使ってもキャッシュに当たるか外れるかです。

しかし

  • 特にアクセスパターンがまばらで予測不可能な場合は、一般にメモリマップの方がランダムアクセスが速くなります。
  • メモリーマップでは、以下のことが可能です。 保つ を使用することで、キャッシュからページを削除することができます。 つまり、あるファイルを長時間酷使した後、一度閉じてから再び開くと、ページがまだキャッシュされていることになります。 とは read の場合、ファイルは何年も前にキャッシュからフラッシュされた可能性があります。 これは、ファイルを使用してすぐに破棄した場合には適用されません。 (もし、あなたが mlock ページをキャッシュに残すことは、ディスクキャッシュを出し抜こうとすることであり、このような愚かな行為はシステムのパフォーマンスにほとんど寄与しません)。
  • ファイルを直接読み込むのは非常にシンプルで高速です。

mmap/readの議論から、他の2つの性能に関する議論を思い出しました。

  • 一部のJavaプログラマは、ノンブロッキングI/OがしばしばブロッキングI/Oよりも遅いことを発見してショックを受けていました。

  • 他のネットワークプログラマーの中には、以下のことを知り、ショックを受けた人もいます。 epoll よりも遅いことが多い。 poll を管理することが分かっているのであれば、これは完全に理にかなっています。 epoll は、より多くのシステムコールを必要とします。

結論 メモリマップを使うのは、データにランダムにアクセスする場合、データを長時間保持する場合、他のプロセスと共有できることがわかっている場合などです( MAP_SHARED は、実際に共有されていない場合は、あまり面白くありません)。 順次アクセスする場合や、読み込んだ後にデータを破棄する場合は、普通にファイルを読み込んでください。 そして、どちらの方法でもプログラムが複雑にならないのであれば、次のようにします。 その . 多くの場合、ベンチマークではなく、実際のアプリケーションをテストすることなく、どちらが速いかを示す確実な方法はないのです。

(ネクロで申し訳ないのですが、答えを探していたらこの質問がGoogleの結果のトップにずっと出てきてしまいました)