IOSプラットフォームは、メモリ不足のシナリオでメモリマップファイルをどのように処理しますか?低メモリシナリオとは、OSがアプリケーション内のすべてのオブザーバーにUIApplicationDidReceiveMemoryWarningNotification
通知を送信するときを意味します。
私たちのファイルは _+[NSData dataWithContentsOfMappedFile:]
_ を使用してメモリにマッピングされます。
マップされたファイルは、仮想メモリ技術を使用して、実際に必要になるまでファイルのページをメモリにコピーしないようにします。
これは、OSがページを使用しなくなったときに、ページのマップも解除することを意味しますか?ページを使用されなくなったものとしてマークすることはできますか?シナリオが変わる場合、このデータは読み取り専用です。 mmap()
を直接使用する場合はどうでしょうか。これは望ましいでしょうか?
メモリマップトファイルは、一度に1ページずつディスクからメモリにデータをコピーします。未使用のページは、mlock(2)
を使用して物理メモリに接続されていない限り、他の仮想メモリと同じように自由にスワップアウトできます。メモリマッピングは、ディスクからメモリに何をコピーし、いつOSにコピーするかを決定します。
mmap
を使用するためにFoundationレベルからBSDレベルにドロップしても、他のFoundationコードとのインターフェイスが必要なコードを作成する以外に、大きな違いが生じる可能性はほとんどありません。
(これは答えではありませんが、役立つ情報になります。)
@ID_AA_Carmackは、iOSメモリマップファイルが低メモリ状態で自動的にマップ解除されますか? (+ [NSData dataWithContentsOfMappedFile]を使用しますか?)
ID_AA_Carmackはこれに返信しました、
@KhrobEdmondsはい、それはiOSでマップトファイルを使用することの大きな利点の1つです。ただし、mmap()を使用します。
それが本当かどうかはわかりません...
私の実験から、NSDataはメモリ警告に応答しません。メモリマップドNSDataを作成し、ファイルの一部にアクセスしてメモリにロードされ、最後にメモリ警告を送信することでテストしました。メモリ警告後、メモリ使用量の減少はありませんでした。ドキュメントには、メモリによってNSDataがメモリ不足の状況で実際のメモリ使用量を減らすとは書かれていないため、メモリの警告に応答しないと私は信じています。たとえば、NSCacheのドキュメントには、メモリ使用量に関してNiceを試してみると書かれていますが、システムが発生するメモリ不足の警告に応答すると言われています。
また、iPod Touch(第4世代)での簡単なテストでは、約600メガバイトのファイルデータを仮想メモリの使用にマッピングすることができました+[NSData dataWithContentsOfMappedFile:]
。次に、NSDataインスタンスのbytesプロパティを介してページへのアクセスを開始しました。私が行ったように、この実メモリーは増加し始めましたが、実メモリー使用量が約30メガバイトで増加しなくなりました。したがって、実装方法では、実際に使用されるメモリの量に上限があるようです。
つまり、NSDataオブジェクトのメモリ使用量を減らしたい場合、最善の策は、オブジェクトが完全に解放されていることを実際に確認し、システムが自動的に実行するものに依存しないことです。
IOSが他のUnixと同じである場合、そしてこの点でお金がかかると思いますが、mmap()領域のページは「スワップアウト」されません。それらは単にドロップされるか(クリーンな場合)、または基になるファイルに書き込まれてからドロップされます(ダーティな場合)。このプロセスは、ページの「削除」と呼ばれます。
メモリマップは読み取り専用であるため、ページは常にクリーンになります。
カーネルは、物理メモリが不足したときに削除するページを決定します。
posix_madvise() を使用して、カーネルにどのページを保持/削除するかについてのヒントを与えることができます。特に、 POSIX_MADV_DONTNEED
カーネルにページを自由に削除するように指示します。またはあなたが言うように、「ページをもう使用されていないものとしてマークする」。
IOSが「不要」のヒントを尊重するかどうかを確認するために、いくつかのテストプログラムを作成するのは非常に簡単なはずです。 BSDから派生しているので、きっとそうなるでしょう。
ファイルバックアップメモリの標準的な仮想メモリ技術では、OSはいつでもページを後で取得できるため、いつでも自由にページを破棄できます。私はiOSを使用していませんが、これは他の多くのオペレーティングシステムでの仮想メモリの動作です。
それをテストする最も簡単な方法は、いくつかの大きなファイルをメモリにマップし、それらを読み取ってメモリにページングすることを保証し、メモリ不足の状況を強制できるかどうかを確認することです。できない場合は、OSがページを使用しなくなったと判断したら、ページのマッピングを解除している必要があります。
dataWithContentsOfMappedFile:
メソッドはiOS5から非推奨になりました。
これらの状況を回避するため、mmapを使用してください。