4

首先,是我得到这个想法的地方:

我曾经写过一个应用程序,它使用了大量的小内存块,每个内存块都用 malloc() 分配。它工作正常,但速度很慢。我只用一个替换了对 malloc 的许多调用,然后在我的应用程序中分割了那个大块。它要快得多。

我正在分析我的应用程序,当我减少 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. 通常的andmalloc函数只使用 给出的空间。当那个空间不够用时,就会制造另一个空间来创造新的空间。通常,空间会增加虚拟内存页面的大小。callocreallocbrkbrk

因此,如果你真的想要一个预制的对象池,那么请确保以页面大小的倍数分配内存。例如,您可以创建一个4KB. 8KB, ... 空间。

下一个想法,看看你的对象。其中一些具有一种尺寸,一些具有其他尺寸。从同一个池中处理所有它们的分配将是一个很大的痛苦。为各种大小的对象创建池(最好是 2 的幂)并从中分配。例如,如果你有一个大小的对象,你会从池中34B为它分配空间。64B

最后,剩余的空间可以不使用,也可以向下移动到其他池中。在上面的例子中,你已经30B离开了。您将其拆分为16B、和块8B,并将每个块添加到各自的池中。4B2B

因此,您将使用链表来管理预先分配的空间。这意味着您的应用程序将使用比实际需要更多的内存,但如果这真的对您有帮助,为什么不呢?

基本上,我所描述的是来自 Linux 内核的伙伴分配器平板分配器之间的混合。

编辑:阅读您的评论后,很容易分配一个大区域malloc(BIG_SPACE)并将其用作您的内存池。

于 2012-09-25T14:03:44.710 回答
1

如果可以,请查看使用具有支持此功能的内存切片 API的glib 。它非常易于使用,并且使您不必重新实现它。

于 2012-09-25T14:06:05.257 回答