« Python 2.7 で ez_setup.py で出るエラーを回避する | メイン | グローバルヒープもHeapCompact可能に »

2014年01月13日

吉里吉里Z 開発:: メモリ断片化低減対策

    

メモリの断片化によって「ビットマップ用メモリを確保できません/……」もしくは「Cannot allocate memory for Bitmap : ……」と言ったエラーが発生することに対する対策を追加した。

メモリ不足はどうしようもないが、断片化はある程度対策がとれる。
比較的大きな領域を確保するビットマップ用のメモリリージョンを別に設ければ、ある程度断片化を防げる。
Windows だとヒープを分けられるので、HeapCreate を使えば断片化が抑止出来るのではないかと考え、これを利用したメモリ確保方法を追加した(実際に効果があるかは不明)。
また、ビットマップはメモリ解放頻度が他と比べて低いと考えられるため、HeapCompact を解放するたびに呼び出す実装とした。
説明を読むと HeapCompact はメモリコンパクションと思われる。
通常、HeapCompact がどの程度の頻度で呼ばれるのかは知らないが、そう頻繁に呼ばれていないのではないかと思われる。

デフォルトは従来と同じ方法となるように bitmapallocator オプションで指定可能とした。
globalalloc を指定すれば従来と同じように GlobalAlloc が使われる。
何も指定しない場合は、これがデフォルト動作となる。
separateheap を指定した場合、上述の HeapCreate が使用されることになる。
malloc を指定した場合は、malloc で確保する。

separateheap を指定した場合、初期ヒープサイズを別に指定できる。
bitmapheapsize オプションで指定可能。
デフォルトは自動で、MEMORYSTATUSEX.ullAvailVirtual から 128MB 引いたサイズ以下で割り当て可能になるまで128MBずつ引いていくような実装になっている。
ullAvailVirtual が 512MB 以下の時は、初期では半分を割り当てようとする。
かなり大きなサイズをこのヒープに割り当てようとするので、グラフィックキャッシュの指定容量が大きいと競合するかもしれない。

「ビットマップ用メモリを確保できません」と言うエラーが出るような状況では、グラフィックキャッシュは使用しない方が好ましい。
キャッシュはメモリが余っている時にするもので、逼迫している時は使わない方が良い。
キャッシュによってメモリが解放されないと、断片化の要因ともなりうる (未開放メモリが間にあるとコンパクションで結合できない)。
断片化によるメモリ不足解消のために separateheap 指定するような状況の場合、グラフィックキャッシュは無効化するであろうことから、競合は考えなくても良いかもしれない。

上記対策に加えて LFH の有効化オプションも追加した。
XP 以降で低メモリ断片化機能 ( LFH ) が追加されているので、uselfh オプションを指定することで有効化できるようにした。
ただ、Vista 以降はデフォルトらしいので、実質的には XP でのみ意味のある機能かもしれない。
デフォルトは従来と同じになるように OFF にしてある (とは言っても、Vista 以降は有効 )。

「ビットマップ用メモリを確保できません」で検索すると何件かエラー報告が上がっているのが見付けられる。
自身の環境で発生したことはないので上記の対策がどの程度効果を発揮するかはわからないが、何もしないよりは効果があるのではないかと思う。



投稿者 Takenori : 2014年01月13日 05:41




comments powered by Disqus
Total : Today : Yesterday : なかのひと