
メモリプール(固定サイズブロック割り当てとも呼ばれる)は、動的なメモリ割り当てを可能にするメモリ管理のためのプールの使用です。動的なメモリ割り当ては、 mallocやC++のoperator newなどの技術を用いることで実現できます。これらの実装は確立され信頼性の高いものですが、可変ブロックサイズのため断片化が発生しやすく、パフォーマンスの観点からリアルタイムシステムでの使用は推奨されません。より効率的な解決策は、メモリプールと呼ばれる同じサイズのメモリブロックを事前に割り当てておくことです。アプリケーションは、実行時にハンドルで表されるブロックを割り当て、アクセスし、解放することができます。
多くのリアルタイム オペレーティング システムでは、トランザクション処理機能などのメモリ プールが使用されます。POCOは、メモリ プール クラスを提供しますPoco::MemoryPool。
ウェブサーバーNginxなどの一部のシステムでは、「メモリプール」という用語が、後で一度に解放できる可変サイズの割り当てのグループを指します。これは「リージョン」とも呼ばれます。リージョンベースのメモリ管理を参照してください。
シンプルなメモリプールの実装
シンプルなメモリプールモジュールは、例えばコンパイル時に3つのプールを割り当てることができ、モジュールをデプロイするアプリケーションに合わせてブロックサイズが最適化されています。アプリケーションは、以下のインターフェースを介してメモリの割り当て、アクセス、解放を行うことができます。
- プールからメモリを割り当てます。この関数は、必要なブロックが収まるプールを特定します。そのプールのすべてのブロックが既に予約されている場合、この関数は次に大きいプールからブロックを探します。割り当てられたメモリブロックは、ハンドルで表されます。
- 割り当てられたメモリへのアクセス ポインターを取得します。
- 以前に割り当てられたメモリ ブロックを解放します。
- ハンドルは、例えば で実装できます
unsigned int。モジュールは、ハンドルをプールインデックス、メモリブロックインデックス、およびバージョンに分割して内部的に解釈します。プールインデックスとメモリブロックインデックスは、ハンドルに対応するブロックへの高速アクセスを可能にします。一方、新しい割り当てごとにインクリメントされるバージョンは、メモリブロックが既に解放されているハンドル(ハンドルが長期間保持されすぎたために発生)を検出します。
メモリプールとmalloc
利点
- メモリプールは、一定の実行時間でメモリ割り当てを可能にします。プール内の数千個のオブジェクトのメモリ解放は、mallocを使用して各オブジェクトにメモリを割り当てる場合のように、1回の操作で済みます。
- メモリ プールは階層的なツリー構造にグループ化することができ、ループや再帰などの特殊なプログラミング構造に適しています。
- 固定サイズのブロックメモリプールでは、割り当てブロックのサイズなどの特性を記述する割り当てメタデータを各割り当てごとに保存する必要がありません。特に小さな割り当ての場合、これにより大幅なスペース節約が実現します。
- メモリ不足エラーを回避することで、リアルタイム システムでの確定的な動作を可能にします。
- 固定サイズのブロックは、外部断片化(使用するには小さすぎる空き領域の断片化)の問題を解消します。[ 1 ]
- 固定サイズのブロックは非移動ガベージコレクションをサポートする[ 1 ]
欠点
- メモリ プールは、それを展開するアプリケーションに合わせて調整する必要がある場合があります。
- 単一のブロックよりも大きなデータ配列を保存すると、システムはプールの多くのブロックに配列を分散させる必要があり、配列が連続している場合よりも配列の要素の読み取りと書き込みが遅くなります。[ 1 ]
参照
参考文献
- ^ a b c Fridtjof Siebert. 「Javaの非移動型ガベージコレクターにおける外部フラグメンテーションの排除」。