3

我们的软件实现了一个actor模型系统,我们经常分配/释放小对象。我非常确定每个对象都会被销毁而不会发生内存泄漏。(我已经使用 valgrind 和 tcmalloc 工具检查了我的软件中的内存泄漏。没有发现泄漏。)

当我们改用 tcmalloc 替换 glibc 中的 malloc 时,我们发现内存不断增加,直到进程被 OOM(Out of Memory)杀死。然后我们发现 glibc 也有同样的问题,但是增长率低于 tcmalloc。

我使用 malloc_stats() 来显示内存信息

首次执行后(顶部显示 0.96G)'


  • MALLOC:960110592(915.6 MB)堆大小
  • MALLOC:15886016 (15.2 MB) 应用程序正在使用的字节数
  • MALLOC:907419648(865.4 MB)页堆中的可用字节
  • MALLOC: 0 ( 0.0 MB) 在页堆中未映射的字节
  • MALLOC:27121208(25.9 MB)中央缓存中的可用字节
  • MALLOC:151040(0.1 MB)传输缓存中的可用字节
  • MALLOC:9532680(9.1 MB)线程缓存中的可用字节
  • MALLOC:14275 跨度正在使用中
  • MALLOC:27 个线程堆正在使用中
  • MALLOC: 7602176 (7.2 MB) 已分配元数据

第 5 次相同执行后(顶部显示 1.2G)

  • MALLOC:1173131264(1118.8 MB)堆大小
  • MALLOC:18001048(17.2 MB)应用程序正在使用的字节
  • MALLOC:1082458112(1032.3 MB)页堆中的可用字节
  • MALLOC:21168128(20.2 MB)字节未映射到页堆中
  • MALLOC:37992328(36.2 MB)中央缓存中的可用字节
  • MALLOC:252928(0.2 MB)传输缓存中的可用字节
  • MALLOC:13258720(12.6 MB)线程缓存中的可用字节
  • MALLOC: 17651 使用中的跨度
  • MALLOC:27 个线程堆正在使用中
  • MALLOC: 8126464 (7.8 MB) 已分配元数据

我们可以从这样的数据中看出。在第 5 次相同的行为之后,我们的软件中只使用了 17.2。但是 tcmalloc 持有 1.1G 内存,不返回系统。当然,tcmalloc 持有那些内存也没关系。但是当我们的程序被OOM杀死时它会不断增加(实际使用的内存小于1G)。

我们怀疑它与堆碎片有关。有人有经验可以和我们分享吗?我想我的情况和 https://bugzilla.redhat.com/show_bug.cgi?id=843478一样

非常感谢。

4

2 回答 2

1

我建议使用Boehm 的保守 GC并在您的应用程序中使用GC_MALLOCandGC_MALLOC_ATOMIC而不是(而不是,但您甚至可以避免任何显式-ing,GC 会这样做)。或者也许使用valgrind(使用系统 Glibc malloc)来查找内存泄漏。如果使用 Boehm 的 GC,不要忘记显式清除分配的内存区域。mallocGC_FREEfreefree

最好确保您的许多小对象具有粗粒度的大小。例如,分配 8 或 12 或 16 个字的对象,而不是 8、9、10、11、12、13、14、15 或 16 个字的对象...例如,您可能只分配大小为 2 或3 次方 2。

另外,不要忘记您可以使用setrlimit(2)来限制内存空间,例如使用ulimit在终端中运行的内置 bash。这应该可以简化测试。此外,也许使用pmapor/proc/$(pidof yourapp)/maps可以帮助您了解所使用的地址空间。

PS。Boehm GC 和任何类型的malloc(包括tcmalloc或 Glibc malloc)都无法解决内存碎片问题。如果您怀疑有碎片,您必须在地址空间中移动内存区域(即您可能想要编写自己的精确、复制、分代 GC 或重新使用一些现有的 GC)。

于 2013-03-22T09:01:10.283 回答
1

tcmalloc 尝试做一些聪明的事情来预测您的内存使用情况,但即使在您释放内存之后,将内存释放回系统也不是很好。实际上,它可能驻留在内存中并导致 OOM。

做这个 :

MallocExtension::instance()->ReleaseFreeMemory();

当您的应用程序预期释放了它预计不会很快使用的内存时。

查看“将内存释放回系统”部分了解更多信息 http://google-perftools.googlecode.com/svn/trunk/doc/tcmalloc.html

还有其他方法,例如设置释放速率,但作为开始,您可以将其洒在代码中并检查驻留内存是否按预期下降。

于 2013-04-04T02:08:54.820 回答