メモリマップトファイルの利点は何ですか?


89

私はプロジェクトのメモリマップトファイルを調査してきましたが、以前にそれらを使用したことがあるか、使用しないことに決めた人からの考えをいただければ幸いです。その理由は何ですか。

特に、重要度の高い順に、次のことが懸念されます。

  • 並行性
  • ランダムアクセス
  • パフォーマンス
  • 使いやすさ
  • 移植性

回答:


56

利点は、ファイルを読み取る従来の方法よりも必要なデータコピーの量を減らすことができることだと思います。

アプリケーションがメモリマップファイルの「インプレース」でデータを使用できる場合、コピーせずにデータを取り込むことができます。システムコール(Linuxのpread()など)を使用する場合、通常、カーネルが独自のバッファーからユーザースペースにデータをコピーする必要があります。この余分なコピーは時間がかかるだけでなく、データのこの余分なコピーにアクセスすることによってCPUのキャッシュの有効性を低下させます。

データを実際にディスクから読み取る必要がある場合(物理I / Oの場合など)、OSはデータを読み込む必要があります。ページフォールトは、システムコールよりもパフォーマンス面で優れているとは言えませんが、そうしないでください(つまり、すでにOSキャッシュにあります)。理論的には、パフォーマンスははるかに優れているはずです。

欠点は、メモリマップファイルへの非同期インターフェイスがないことです。マップされていないページにアクセスしようとすると、ページフォールトが生成され、スレッドがI / Oを待機します。


メモリマップトファイルの明らかな欠点は、32ビットOS上にあることです。アドレス空間が簡単に不足する可能性があります。


4
少なくともWindowsでは、より大きなmmapファイルの複数の32ビットビューをマップできます。これは、通常のCRT関数を使用して非常に大きなファイルを処理するよりも効率的です
Martin Beckett

@MarkRあなたは、「彼の余分なコピーは時間がかかるだけでなく、データのこの余分なコピーにアクセスすることによってCPUのキャッシュの有効性を低下させる」と書いています。(私の強調)。カーネル内の余分なバッファコピーがCPUのキャッシュの有効性をどのように妨げるかを説明できますか?
オタク2014

4
@Geekが2倍のメモリにアクセスする= 2倍のキャッシュが無駄になります(ほぼ)。
user253751 2015年

49

ユーザーが入力している間、メモリマップファイルを使用して「オートコンプリート」機能を実装しました。1つのインデックスファイルに100万をはるかに超える製品部品番号が保存されています。ファイルにはいくつかの典型的なヘッダー情報がありますが、ファイルの大部分はキーフィールドでソートされた固定サイズのレコードの巨大な配列です。

実行時に、ファイルはメモリマップされ、Cスタイルのstruct配列にキャストされます。バイナリ検索を実行して、ユーザーが入力したときに一致する部品番号を見つけます。ファイルのいくつかのメモリページのみが実際にディスクから読み取られます-バイナリ検索中にヒットしたページ。

  • 同時実行性-同じプロセススペースでファイルを複数回メモリマップするという実装上の問題がありました。これは、ファイルをマップするのに十分な大きさの仮想メモリの空きブロックがシステムで見つからないことがあったため、私が覚えている問題でした。解決策は、ファイルを1回だけマップし、そのファイルへのすべての呼び出しをサンクすることでした。振り返ってみると、本格的なWindowsサービスを使用するのはすばらしいことです。
  • ランダムアクセス-バイナリ検索は確かにランダムアクセスであり、非常に高速です
  • パフォーマンス-ルックアップは非常に高速です。ユーザーが入力すると、ポップアップウィンドウに一致する製品の部品番号のリストが表示され、入力を続けるとリストが縮小します。入力中に目立った遅れはありません。

1
試行ごとにページが読み込まれるため、バイナリ検索は遅くなりませんか?または、オペレーティングシステムは、これを効率的に処理するのに十分スマートですか?
jjxtra 2013年

1
バイナリ検索では、比較的離れたメモリ位置にあるいくつかの単一キーにしかアクセスできないため、メモリマップドI / Oを使用するのは無駄だと思いますが、OSはそのような要求ごとに4kページで読み込まれます。しかし、繰り返しになりますが、パーツを含むファイルはあまり変更されないため、キャッシュはこれをカバーするのに役立ちます。しかし厳密に言えば、ここでは伝統的な探求/読書の方が良いと思います。最後に、最近では1ミルはそれほど多くありません。すべてをRAMに保存してみませんか?

5
@the swine and PsychoDad私の最初の答えは2008年のもので、このメモリマップドオートコンプリート機能の実際の実装は2004年から2005年頃でした。ファイル全体をロードするために800〜1000 MBの物理メモリを消費することは、ユーザーベースにとって適切なソリューションではありませんでした。メモリマップドソリューションは非常に高速で効率的でした。それはお尻を蹴った、そして私はそれを私の初期のジュニア開発者の時代から愛情を込めて覚えている。:)
Brian Ensink 2013年

@BrianEnsink:わかりました、それは理にかなっています。各エントリが1kBになるとは思っていませんでした。もちろん、ページングされたアプローチはより効率的になります。いいです:)

22

メモリマップトファイルは、読み取り/書き込みアクセスを置き換えるため、または同時共有をサポートするために使用できます。それらを1つのメカニズムに使用すると、もう1つのメカニズムも取得します。

ファイルを探したり、書き込んだり、読み取ったりするのではなく、ファイルをメモリにマップして、期待する場所にアクセスするだけです。

これは非常に便利であり、仮想メモリインターフェイスによってはパフォーマンスを向上させることができます。オペレーティングシステムが他のすべてのプログラムメモリアクセスとともにこの以前の「ファイルI / O」を管理できるようになり、(理論的には)すでにサポートに使用されているページングアルゴリズムなどを活用できるため、パフォーマンスが向上する可能性があります。プログラムの残りの部分の仮想メモリ。ただし、基盤となる仮想メモリシステムの品質によって異なります。私が聞いた逸話では、Solarisおよび* BSD仮想メモリシステムはLinuxのVMシステムよりも優れたパフォーマンスの向上を示す可能性がありますが、これをバックアップするための経験的データはありません。YMMV。

マップされたメモリを介して同じ「ファイル」を使用する複数のプロセスの可能性を検討すると、並行性が浮き彫りになります。読み取り/書き込みモデルでは、2つのプロセスがファイルの同じ領域に書き込んだ場合、プロセスのデータの1つがファイルに到着し、他のプロセスのデータを上書きすることはほぼ確実です。あなたはどちらか一方を手に入れるでしょう-しかし、いくつかの奇妙な混ざり合いはありません。これが標準で義務付けられている動作であるかどうかはわかりませんが、かなり信頼できるものです。(実際には良いフォローアップの質問です!)

対照的に、マップされた世界では、2つのプロセスが両方とも「書き込み」であると想像してください。これを行うには、「メモリストア」を実行します。これにより、O / Sがデータをディスクにページアウトします(最終的には)。ただし、その間に、重複する書き込みが発生することが予想されます。

これが例です。2つのプロセスが両方ともオフセット1024で8バイトを書き込んでいるとします。プロセス1は「11111111」を書き込んでおり、プロセス2は「22222222」を書き込んでいます。ファイルI / Oを使用している場合、O / Sの奥深くに、1でいっぱいのバッファーと、2でいっぱいのバッファーがあり、どちらもディスク上の同じ場所に向かっていることが想像できます。それらの1つは最初にそこに到達し、もう1つは2番目に到達します。この場合、2番目のものが勝ちます。 ただし、メモリマップトファイルアプローチを使用している場合、プロセス1は4バイトのメモリストアに移動し、続いて4バイトの別のメモリストアに移動します(これが最大メモリストアサイズではないと仮定します)。プロセス2も同じことをします。プロセスがいつ実行されるかに基づいて、次のいずれかが表示されると予想できます。

11111111
22222222
11112222
22221111

これに対する解決策は、明示的な相互排除を使用することです。これは、いずれにしてもおそらく良い考えです。とにかく、ファイルの読み取り/書き込みI / Oの場合、「正しいこと」を行うためにO / Sに依存していました。

分類相互排除プリミティブはミューテックスです。メモリマップトファイルの場合、(たとえば)pthread_mutex_init()を使用して利用できるメモリマップトミューテックスを確認することをお勧めします。

1つの落とし穴で編集する:マップされたファイルを使用している場合、ファイル内のデータへのポインターをファイル自体に埋め込みたいという誘惑があります(マップされたファイルに格納されているリンクリストを考えてください)。ファイルは異なる絶対アドレスに異なる時間に、または異なるプロセスでマップされる可能性があるため、これは望ましくありません。代わりに、マップされたファイル内でオフセットを使用してください。


1

並行性が問題になります。ランダムアクセスが簡単ですパフォーマンスは良いものから素晴らしいものまであります。使いやすさ。あまり良くありません。移植性-それほど熱くはありません。

私はずっと前にSunシステムでそれらを使用しました、そしてそれらは私の考えです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.