Visual Studio 2008 C ++アプリケーションがあり、標準コンテナーにカスタムアロケータを使用して、メモリがヒープではなくメモリマップトファイルから取得されるようにしています。このアロケータは、4つの異なるユースケースで使用されます。
- 104バイトの固定サイズ構造
std::vector< SomeType, MyAllocator< SomeType > > foo;
- 200バイトの固定サイズ構造
- 304バイトの固定サイズ構造
- nバイトの文字列
std::basic_string< char, std::char_traits< char >, MyAllocator< char > > strn;
これらのそれぞれに合計約32MBを割り当てることができる必要があります。
std::map
アロケータは、割り当てサイズへのポインタを使用してメモリ使用量を追跡します。typedef std::map< void*, size_t > SuperBlock;
各スーパーブロックは4MBのメモリを表します。
std::vector< SuperBlock >
1つのSuperBlockに十分なスペースがない場合に備えて、これらがあります。
アロケータに使用されるアルゴリズムは次のようになります。
- スーパーブロックごとに:スーパーブロックの最後にスペースはありますか?そこに割り当てを置きます。(速い)
- そうでない場合は、各SuperBlock内で十分なサイズの空きスペースを検索し、そこに割り当てを配置します。(スロー)
- まだ何もありませんか?別のSuperBlockを割り当て、その割り当てを新しいSuperBlockの先頭に配置します。
残念ながら、ステップ2はしばらくすると非常に遅くなる可能性があります。オブジェクトのコピーが作成され、一時変数が破棄されると、多くの断片化が発生します。これにより、メモリ構造内で多くの詳細な検索が発生します。使用できるメモリの量が限られているため、断片化が問題になっています(下記の注を参照)
プロセスをスピードアップするこのアルゴリズムの改善を誰かが提案できますか?2つの別々のアルゴリズム(1つは固定サイズの割り当て用、もう1つは文字列アロケータ用)が必要ですか?
注:理由が必要な場合:ヒープに32MBのプロセススロット制限があるWindowsMobileでこのアルゴリズムを使用しています。だから、いつもstd::allocator
はそれをカットしません。十分なスペースを確保するために、1GBの大容量メモリ領域に割り当てを配置する必要があります。