4

まず、ここからアイデアを得ました。

かつて私が書いた、たくさんの小さなメモリの塊を使用し、それぞれがmalloc()で割り当てられたアプリがありました。正しく動作しましたが、低速でした。私はmallocへの多くの呼び出しを1つだけに置き換えてから、アプリ内でその大きなブロックをスライスしました。それははるかに速かった。

アプリケーションのプロファイリングを行っていましたが、malloc呼び出しの数を減らすと、パフォーマンスが予想外に向上しました。ただし、まだ同じ量のメモリを割り当てています。

だから、私はこの男がしたことをしたいのですが、それを行うための最良の方法がわかりません。

私の考え:

// static global variables
static void * memoryForStruct1 = malloc(sizeof(Struct1) * 10000);
int struct1Index = 0;
...
// somewhere, I need memory, fast:
Struct1* data = memoryForStruct1[struct1Index++];
...
// done with data:
--struct1Index;

落とし穴:

  • 10000を超えないようにする必要があります
  • 占有したのと同じ順序でメモリを解放する必要があります。(私の場合、再帰を使用しているので大きな問題ではありませんが、可能であればそれを避けたいと思います)。

Mihai Maruseacからのインスピレーション:

intまず、基本的にどのメモリインデックスが空いているかを示すリンクリストを作成します。次に、呼び出された構造にプロパティを追加しましたint memoryIndex。これは、占有されているメモリを任意の順序で返すのに役立ちます。そして幸いなことに、私のメモリの必要量はいつでも5 MBを超えることはないと確信しているので、その量のメモリを安全に割り当てることができます。解決しました。

4

2 に答える 2

5

あなたに記憶を与えるシステムコールはですbrk。通常の関数malloccallocrealloc関数は、単に。で指定されたスペースを使用しbrkます。そのスペースが足りないときは、別のbrkスペースを作って新しいスペースを作ります。通常、スペースは仮想メモリページのサイズで増加します。

したがって、オブジェクトの事前作成されたプールが本当に必要な場合は、ページサイズの倍数でメモリを割り当てるようにしてください。たとえば、のプールを1つ作成できます4KB8KB、 ... スペース。

次のアイデアは、オブジェクトを見てください。それらのいくつかは1つのサイズを持ち、いくつかは他のサイズを持ちます。同じプールからそれらすべての割り当てを処理するのは大きな苦痛になります。さまざまなサイズのオブジェクト(2の累乗が最適)のプールを作成し、それらから割り当てます。たとえば、サイズのオブジェクトがある場合は34B、プールからそのオブジェクトにスペースを割り当て64Bます。

最後に、残りのスペースは未使用のままにするか、他のプールに移動することができます。上記の例では、あなたは30B去りました。、、、およびチャンクに分割し16B、各チャンクをそれぞれのプールに追加します。8B4B2B

したがって、リンクリストを使用して、事前に割り当てられたスペースを管理します。つまり、アプリケーションは実際に必要な量よりも多くのメモリを使用しますが、これが本当に役立つ場合は、どうでしょうか。

基本的に、私が説明したのは、Linuxカーネルのバディアロケータースラブアロケーターの組み合わせです。

編集malloc(BIG_SPACE):コメントを読んだ後、大きな領域を割り当てて、これをメモリのプールとして使用するのは非常に簡単です。

于 2012-09-25T14:03:44.710 に答える
1

可能であれば、これをサポートするメモリスライシングAPIを備えたglibの使用を検討してください。使い方はとても簡単で、再実装する必要がありません。

于 2012-09-25T14:06:05.257 に答える