mmap() はシーケンシャル IO よりも高速であると聞きました (インターネットのどこかで読んだ)。これは正しいです?はいの場合、なぜ高速なのですか?
それは可能です-以下にリストされている長所と短所があります。 本当に気にする理由がある場合は、常に両方をベンチマークしてください .
実際の IO 効率とは別に、アプリケーション コードが I/O を実行する必要があるタイミングを追跡し、データの処理/生成を行う方法には影響があり、パフォーマンスに非常に劇的な影響を与える場合があります。
<ブロック引用> <オール>では、mmap() は実際にはファイルからの read() よりも遅いはずですか?上記の私の仮定のうち、間違っているものはどれですか?
<オール>
間違っています... mmap()
ファイルコンテンツに対応する仮想アドレス空間の領域を割り当てます...そのアドレス空間のページがアクセスされるたびに、物理RAMが仮想アドレスをバックアップするために検出され、対応するディスクコンテンツがそのRAMにフォールトされます.したがって、ディスクからの読み取り順序は、アクセスの順序と一致します。これは「怠惰な」I/O メカニズムです。たとえば、ディスクから読み取る巨大なハッシュ テーブルにインデックスを付ける必要がある場合は、 mmap
ファイルにアクセスしてアクセスを開始すると、ディスク I/O がシーケンシャルに実行されないため、ファイル全体がメモリに読み込まれるまでの経過時間が長くなる可能性がありますが、その間、ルックアップは成功し、依存する作業を行うことができます。ファイルの一部が実際に必要とされない場合、それらは読み取られません (ディスクとメモリ ページの粒度を考慮し、メモリ マッピングを使用する場合でも、多くの OS では、計画に関するパフォーマンス向上/メモリ効率のヒントを指定できます)。パターンにアクセスして、プロアクティブに先読みしたり、メモリをより積極的に解放したりできるようにします)。
絶対に真実
「マッピングされた領域は連続していません」はあいまいです。メモリ マップ領域は、仮想アドレス空間で「連続」(シーケンシャル) します。上記で、ディスク I/O がシーケンシャルであることについて説明しました。それとも、何か他のことを考えていますか?いずれにせよ、ページがフォールト インしている間は、実際には DMA を使用して転送される可能性があります。
さらに、メモリ マッピングが通常の I/O よりも優れている理由は他にもあります。
- コピーが少ない:
- 多くの場合、OS およびライブラリ レベルのルーチンは、データがアプリケーション指定のバッファに到達する前に 1 つまたは複数のバッファを介してデータを渡します。その後、アプリケーションはストレージを動的に割り当て、I/O バッファからそのストレージにコピーして、ファイルの後でデータを使用できるようにします。読み取り完了
- メモリ マッピングにより、インプレースでの使用が可能になります (ただし強制はされません) (ポインタと場合によっては長さを記録するだけでかまいません)
- インプレースでデータにアクセスし続けると、キャッシュ ミスや後でスワッピングが増加するリスクがあります。ファイル/メモリ マップは、解析可能なデータ構造よりも冗長になる可能性があるため、その中のデータのアクセス パターンでより多くの遅延が発生する可能性があります。より多くのメモリ ページでフォールトする
- メモリ マッピングを使用すると、別のバッファがいっぱいになるタイミングを気にすることなく、アプリケーションがファイル コンテンツ全体をアクセス可能として処理できるため、アプリケーションの解析ジョブを簡素化できます
- アプリケーションは、任意の時点で物理 RAM にあるページ数に関して OS の知恵にさらに委ね、直接アクセス ディスク キャッシュをアプリケーションと効果的に共有します
- 「メモリ マッピングを使用すると、通常はシステム コールの使用量が減ります」
- 複数のプロセスが同じファイルにアクセスしている場合、物理的なバッキング ページを共有できる必要があります
mmap
の理由でもあります もっと遅いかもしれません - mmap
について述べている Linus Torvald の投稿をここで読んでください :
...ページ テーブル ゲームと障害 (TLB ミスだけでも) のオーバーヘッドは、ナイス ストリーミング方式でページをコピーするコストを簡単に上回ります...
そして彼の別の投稿から:
- セットアップと撤去のコストが非常に高くなります。つまり、目立つ .ページテーブルをたどってすべてをきれいにアンマップするようなものです。これは、すべてのマッピングのリストを維持するための簿記です。マッピングを解除した後に必要な TLB フラッシュです。
- ページ フォールトはコストがかかります。このようにしてマッピングが生成されますが、かなり時間がかかります。
Linux には「ヒュージページ」 (つまり、4kb ごとではなく 2MB ごとに 1 つの TLB エントリ) と、アプリケーション コードがそれらを明示的に利用するように書かれていなくても、OS がそれらを使用しようとする透過的なヒュージ ページさえあります。
FWIW、これが職場で最後に発生したとき、メモリ マップ入力は fread
より 80% 高速でした バイナリ データベース レコードをプロプライエタリ データベースに読み込み、64 ビット Linux で最大 170 GB のファイルを使用。
<オール>
mmap()
プロセス間で共有できます。mmap
分のメモリ カーネルによって割り当てられ、常に整列されます。