8

I need some clarifications for the concept & implementation on memory pool.

By memory pool on wiki, it says that

also called fixed-size-blocks allocation, ... , as those implementations suffer from fragmentation because of variable block sizes, it can be impossible to use them in a real time system due to performance.

How "variable block size causes fragmentation" happens? How fixed sized allocation can solve this? This wiki description sounds a bit misleading to me. I think fragmentation is not avoided by fixed sized allocation or caused by variable size. In memory pool context, fragmentation is avoided by specific designed memory allocators for specific application, or reduced by restrictly using an intended block of memory.

Also by several implementation samples, e.g., Code Sample 1 and Code Sample 2, it seems to me, to use memory pool, the developer has to know the data type very well, then cut, split, or organize the data into the linked memory chunks (if data is close to linked list) or hierarchical linked chunks (if data is more hierarchical organized, like files). Besides, it seems the developer has to predict in prior how much memory he needs.

Well, I could imagine this works well for an array of primitive data. What about C++ non-primitive data classes, in which the memory model is not that evident? Even for primitive data, should the developer consider the data type alignment?

Is there good memory pool library for C and C++?

Thanks for any comments!

4

5 に答える 5

14

可変ブロックサイズは確かに断片化を引き起こします。私が添付している写真を見てください:ここに画像の説明を入力

画像 (ここから) は、A、B、および C がメモリのチャンク、可変サイズのチャンクを割り当てる状況を示しています。

ある時点で、B がメモリのすべてのチャンクを解放すると、突然断片化が発生します。たとえば、C がメモリの大きなチャンクを割り当てる必要がある場合、それはまだ利用可能なメモリに収まりますが、利用可能なメモリが 2 つのブロックに分割されているため、それを行うことができませんでした。

ここで、メモリの各チャンクが同じサイズになる場合を考えると、この状況は明らかに発生しません。

もちろん、あなた自身が指摘しているように、メモリプールには独自の欠点があります。したがって、メモリ プールを魔法の杖だと考えるべきではありません。これにはコストがかかり、特定の状況 (つまり、メモリが限られている組み込みシステム、リアルタイムの制約など) ではコストを支払うのが理にかなっています。

C++ でどのメモリ プールが適しているかについては、場合によって異なります。OSによって提供されたVxWorksの下で使用しました。ある意味で、優れたメモリ プールは、OS と緊密に統合されている場合に効果的です。実際には、各 RTOS がメモリ プールの実装を提供していると思います。

一般的なメモリ プールの実装を探している場合は、このを参照してください。

編集:

あなたの最後のコメントから、断片化の問題に対する「解決策」としてメモリプールを考えているように思えます。残念ながら、そうではありません。お望みであれば、断片化はメモリ レベルでのエントロピーの現れです。つまり、断片化は避けられません。一方、メモリプールは、断片化の影響を効果的に減らすような方法でメモリを管理する方法です (私が言ったように、そしてウィキペディアが言及したように、主にリアルタイムシステムのような特定のシステムで)。これにはコストがかかります。メモリ プールは、ブロック サイズが最小であるという点で、「通常の」メモリ割り当て手法よりも効率が悪い可能性があるためです。言い換えれば、エントロピーは変装して再び現れます。

さらに、ブロック サイズ、ブロック割り当てポリシー、またはメモリ プールが 1 つだけか、異なるブロック サイズ、異なる寿命、または異なるポリシーを持つ複数のメモリ プールがあるかなど、メモリ プール システムの効率に影響を与える多くのパラメータがあります。

メモリ管理は実際には複雑な問題であり、メモリ プールは他の技術と同様に、他の技術と比較して物事を改善し、独自のコストを正確に計算する技術にすぎません。

于 2011-07-19T13:37:37.103 に答える
5

常に固定サイズのブロックを割り当てるシナリオでは、もう 1 つのブロックに十分なスペースがあるか、ないかのどちらかです。ある場合、ブロックは使用可能なスペースに収まります。これは、すべての空きスペースまたは使用済みスペースが同じサイズであるためです。断片化は問題ではありません。

可変サイズのブロックを使用するシナリオでは、さまざまなサイズの複数の個別の空きブロックが発生する可能性があります。空きメモリの合計よりも小さいサイズのブロックに対する要求は、十分な大きさの連続したブロックが 1 つもないため、満足できない場合があります。たとえば、最終的に 2KB の 2 つの別々の空きブロックがあり、3KB の要求を満たす必要があるとします。十分なメモリが利用可能であっても、これらのブロックのどちらもそれを提供するのに十分ではありません。

于 2011-07-19T13:44:51.007 に答える
2

固定サイズと可変サイズの両方のメモリ プールはフラグメンテーションを特徴とします。つまり、使用されているメモリ チャンクの間にいくつかの空きメモリ チャンクが存在します。

可変サイズの場合、要求された特定のサイズに対して十分な空きチャンクがない可能性があるため、これは問題を引き起こす可能性があります。

一方、固定サイズのプールの場合は、事前に定義されたサイズの一部しか要求できないため、これは問題ではありません。空き領域がある場合、1 つの部分 (の倍数) に十分な大きさであることが保証されます。

于 2011-07-19T13:42:59.150 に答える
1

ハード リアルタイム システムを実行する場合は、許容される最大時間内でメモリを割り当てることができることを事前に知っておく必要がある場合があります。これは、固定サイズのメモリ プールで「解決」できます。

私はかつて軍事システムで働いていました。そこでは、システムが使用できる可能性のある各サイズのメモリ ブロックの最大数を計算する必要がありました。次に、それらの数値が総計に追加され、システムはその量のメモリで構成されました。

非常に高価ですが、防衛のために働きました。


いくつかの固定サイズのプールがある場合、他のプールに十分なスペースがある場合でも、プールのブロックがなくなる二次断片化が発生する可能性があります。それをどのように共有しますか?

于 2011-07-19T13:43:56.370 に答える
1

メモリ プールを使用すると、操作は次のように機能します。

  1. 使用可能なオブジェクトのリストであるグローバル変数を保存します (最初は空です)。
  2. 新しいオブジェクトを取得するには、使用可能なグローバル リストからオブジェクトを取得してみてください。存在しない場合は、演算子 new を呼び出して、ヒープに新しいオブジェクトを割り当てます。割り当ては非常に高速です。これは、現在メモリ割り当てに多くの CPU 時間を費やしている可能性がある一部のアプリケーションにとって重要です。
  3. オブジェクトを解放するには、使用可能なオブジェクトのグローバル リストに追加するだけです。グローバル リストで許可されるアイテムの数に上限を設けることができます。上限に達した場合、オブジェクトはリストに返される代わりに解放されます。キャップは、大規模なメモリ リークの発生を防ぎます。

これは、同じサイズの単一のデータ型に対して常に行われることに注意してください。より大きなものでは機能せず、おそらく通常どおりヒープを使用する必要があります。

実装は非常に簡単です。この戦略をアプリケーションで使用します。これにより、プログラムの開始時に一連のメモリ割り当てが発生しますが、大きなオーバーヘッドが発生するメモリの解放/割り当ては発生しません。

于 2011-07-19T13:44:35.747 に答える