私は主に O(1) Small Block Memory Manager (SBMM) を使用しています。基本的には次のように動作します。
1) OS からより大きなスーパーブロックを割り当て、開始アドレスと終了アドレスを範囲として追跡します。SuperBlock のサイズは調整可能ですが、1MB で十分なサイズになります。
2) SuperBlocks はブロックに分割されます (サイズも調整可能です...アプリによっては 4K-64K が適しています)。これらの各ブロックは、特定のサイズの割り当てを処理し、ブロック内のすべての項目を単独でリンクされたリストとして格納します。SuperBlock を割り当てると、フリー ブロックのリンク リストが作成されます。
3) アイテムの割り当てとは、A) そのサイズを処理する空きアイテムを含むブロックがあるかどうかを確認することを意味します。ない場合は、スーパーブロックから新しいブロックを割り当てます。B) ブロックの空きリストからアイテムを削除する。
4) アドレスによるアイテムの解放 A) アドレス (*) を含むスーパーブロックの検索 B) スーパーブロック内のブロックの検索 (スーパーブロックの開始アドレスを減算し、ブロック サイズで割る) C) ブロックのフリー アイテム リストにアイテムを押し戻す。
前述したように、この SBMM は O(1) パフォーマンス (*) で実行されるため、非常に高速です。私が実装したバージョンでは、AtomicSList (Windows の SLIST に似ています) を使用して、実装で O(1) パフォーマンスだけでなく、ThreadSafe と LockFree も実現できるようにしています。必要に応じて、実際に Win32 SLIST を使用してアルゴリズムを実装できます。
興味深いことに、スーパーブロックからのブロックまたはブロックからの項目を割り当てるためのアルゴリズムは、ほぼ同一のコードになります (どちらもフリー リストからの O(1) 割り当てです)。
(*) スーパーブロックは、平均パフォーマンスが O(1) の範囲マップに配置されます (ただし、N がスーパーブロックの数である場合、最悪の場合は O(Lg N) になる可能性があります)。範囲マップの幅は、O(1) のパフォーマンスを得るために必要なメモリ量を大まかに把握することに依存します。オーバーシュートすると、メモリが少し無駄になりますが、それでも O(1) のパフォーマンスが得られます。アンダーシュートすると、O(Lg N) のパフォーマンスに近づきますが、N は SuperBlock の数であり、アイテムの数ではありません。SuperBlock の数は Item の数に比べて非常に少ないため (私のコードではバイナリで約 20 桁)、残りのアロケーターほど重要ではありません。