2011-07-19 11 views
6

私はメモリプール上の実装&の概念についていくつかの明確化が必要です。 wikiにmemory poolことでメモリプールについての質問

、それは

も、固定サイズブロ​​ックの割り当てと呼ばれること...、 それらの実装があるため、可変 ブロック・サイズの断片化に苦しんでいるとして、それが不可能であると言いますパフォーマンスのためにリアルタイムシステム でそれらを使用してください。

"可変ブロックサイズによって断片化が発生する"とはどういう意味ですか?どのように固定サイズの割り当てがこれを解決することができますか?このwikiの説明は私に少し誤解を招くようです。私は断片化が固定サイズの割り当てによって回避されたり、可変サイズによって引き起こされたりしないと考えます。メモリプールコンテキストでは、特定のアプリケーション用に特別に設計されたメモリアロケータによってフラグメンテーションが回避されます。または、意図されたメモリブロックを使用して制限されます。

また、Code Sample 1Code Sample 2などのいくつかの実装サンプルでは、​​メモリプールを使用すると思われます。開発者はデータ型をよく知っていて、データをリンクされたメモリに分割、分割、または整理する必要があります。チャンク(データがリンクされたリストに近い場合)または階層リンクチャンク(データがファイルのように整理された階層構造の場合)また、開発者は、必要なメモリ量を事前に予測する必要があるようです。

これは、プリミティブデータの配列に対してうまく機能すると思います。メモリモデルがそれほど明らかではないC++の非プリミティブデータクラスはどうでしょうか?原始的なデータであっても、開発者はデータ型の整列を考慮すべきでしょうか?

CおよびC++に適したメモリプールライブラリはありますか?

ありがとうございました!

+4

基本的な考え方は、各オブジェクトが同じ空間を必要とするように、オブジェクトの各クラスごとに1つのプールがあることだと思います。これにより、解放されたブロックを正確に再利用できるため、メモリの割り当て、解放、再利用が容易に行えます。 –

+0

こんにちは、Kerrek SB、ご意見ありがとうございます。 1つのクラス・タイプのプールが1つの場合、プールが多数存在するか、または1つのクラスが設計されるたびに1つのメモリー・プールが設計されます。これが正しければ、ちょっと面倒ですね。 – pepero

+1

メモリプールの実装が、割り当てが許可されている項目の型によってテンプレート化されている場合は、コンパイラによって隠されて、必要な定型コードを大量に生成します。 – Chad

答えて

3

固定サイズブロ​​ックを常に割り当てるシナリオでは、もう1つのブロックに十分な領域があるか、そうでない場合があります。あなたが持っているならば、空きスペースや空きスペースはすべて同じサイズなので、ブロックは空きスペースに収まります。断片化は問題ではありません。

可変サイズのブロックを使用するシナリオでは、さまざまなサイズの複数の独立したフリーブロックになる可能性があります。空きである総メモリよりも小さいサイズのブロックに対する要求は、十分に大きな1つの連続したブロックが存在しないため、満たすことは不可能かもしれない。たとえば、2KBの2つの独立した空きブロックがあり、3KBの要求を満たす必要があるとします。十分なメモリが利用可能であるにもかかわらず、これらのブロックのいずれも十分なものではありません。

+0

ありがとう、Martinho。 「どのデータサイズが必要なのか、どのプールが作成されたのか」が真であれば、メモリプールを理解できます。もちろん、すべての汎用プールではなく特定のプールが優先されます。 " – pepero

+0

はい固定サイズブロ​​ックのメモリプールは、通常、特定のデータ型に固有ですテンプレートを使って一般的な実装を書くことができますが、各プールには同じタイプのオブジェクトしかないので、固定サイズです。 –

12

可変ブロックサイズは実際に断片化を引き起こします。私が付いている画像を見てください。enter image description here

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

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

ここで、メモリの各チャンクが同じサイズであるケースについて考えると、この状況は明らかに発生しません。

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

C++でどのメモリプールが良いのかは、依存すると言います。私はOSによって提供されたVxWorksのもとで1つを使用しました。ある意味では、OSと緊密に統合されていると、良好なメモリプールが有効になります。実際、各RTOSはメモリプールの実装を提供しているようです。

汎用メモリプールの実装をお探しの場合はthisをご覧ください。

EDIT:あなたから

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

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

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

+0

おかげさまでセルジオは、「メモリの各チャンクが同じサイズになるケースについて考えると、この状況は明らかに発生しません」と述べています。あなたは単一のデータ型しか持たない限り、どのように同じサイズの各チャンクに対して可能ですか? – pepero

+0

HI、セルジオ、私は画像リンクを読んだ。残念なことに、これは外部の断片化に関する典型的なサンプルの紹介で、Martinho Fernandesandが彼の記事で説明しているようです。私はこれが私の質問を明確にしていないと思う。例えば、同じサイズでも連続していない可能性があり、cは依然としてメモリを要求できません。 – pepero

2

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

可変サイズの場合、要求されたサイズに十分な大きさの空きチャンクがない可能性があるため、問題が発生する可能性があります。

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

1

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

私はかつて軍用システムで働いていましたが、システムで使用できる可能性のある各サイズのメモリブロックの最大数を計算しなければなりませんでした。その後、それらの数値が総計に加算され、その量のメモリがシステムに設定されました。

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


あなたはいくつかの固定サイズのプールを持っている場合、あなたはあなたのプールは他のいくつかのプール内のスペースが十分にあるにもかかわらず、ブロックの外にある二次フラグメンテーションを得ることができます。どのようにそれを共有しますか?メモリプール付き

+0

それはまた質問したい質問ですが、「1つのタイプのプール」を学んだ後、どうなりますか? – pepero

1

、操作は次のように動作するかもしれません:

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

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

実装が非常に簡単です。この戦略をアプリケーションで使用します。これにより、プログラムの先頭に多数のメモリ割り当てが発生しますが、それ以上のメモリ解放/割り当ては発生せず、重大なオーバーヘッドが発生します。

+0

こんにちは、ジェームズ、 "メモリプールは常に同じサイズの単一のデータ型に対して行われる"場合、私たちはどのような種類のデータプールを選択するのですか? – pepero

+0

保存しようとしているデータタイプによって異なります。この例では、すべて同じ次元の画像を処理していました。つまり、画像のピクセルを表す2次元配列/マトリックスでした。グローバル変数はポインタの配列でした。 –