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