我有频繁的内存分配,释放长期生活应用。 将所有的malloc实现回报释放的内存回系统?
是什么,在这方面,的行为:
- ptmalloc 1,2(glibc的默认值)或3
- dlmalloc
- tcmalloc(谷歌螺纹的malloc)
- 在solaris 10-11默认的malloc和为mtmalloc
- FreeBSD的8默认的malloc(jemalloc)
- 囤积居奇的malloc?
更新
如果我有一个应用程序,它的内存消耗可以在白天和夜间(例如)非常不同,我可以强制任何的malloc的到释放的内存返回到系统?
如果没有这样的回报率释放的内存将被换出,并在很多次,但这种记忆只包含垃圾。
以下分析仅适用于glibc的(基于ptmalloc2算法)。 有迹象表明,似乎有助于回返回释放的内存给系统的某些选项:
mallopt() (定义在malloc.h
)不提供一个选项来设置使用参数选项之一修剪阈值M_TRIM_THRESHOLD
,这指示允许在该数据段的顶部的自由存储器(以字节计)的最小量。 如果量低于这个阈值,glibc的调用brk()
来回馈内存的内核。
默认值M_TRIM_THRESHOLD
在Linux中设置为128K,设置较小的值可能节省空间。
同样的行为可以通过在环境变量设置微调阈值来实现MALLOC_TRIM_THRESHOLD_
,完全没有来源的变化。
然而,初步试验程序的运行使用M_TRIM_THRESHOLD
表明即使由malloc的分配的内存并返回到系统中,存储器(竞技场)通过最初所请求的实际数据块的剩余部分brk()
趋向于被保留。
是可能的修剪存储器舞台,并通过调用给任何未使用的存储器回系统malloc_trim(pad)
(定义在malloc.h
)。 该功能调整大小的数据段,留下至少pad
在它的结束字节,如果失败的字节少于一个页面值得可以被释放。 段大小始终是一个网页,这是在i386上4096个字节的倍数。
对于这个修改行为的实现free()
使用malloc_trim
可以使用malloc的钩功能来完成。 这不需要任何修改源代码的核心glibc库。
使用madvise()
的免费实现的glibc的内部系统调用。
大多数的实现不打扰查明整个“块”(无论大小适合OS)已被释放,并可能会返回那些(比较少见)的情况下,但也有例外当然的。 例如,我从引用维基百科页面 ,在OpenBSD的:
在一个通话free
,内存被释放,并使用munmap从进程的地址空间解除映射。 这一制度旨在通过利用作为OpenBSD的一部分实施的地址空间布局随机化和差距页面的功能优势,以提高安全性mmap
系统调用,并检测释放后使用无漏洞,作为一个大的内存分配是完全映射的是后中解脱出来,进一步使用导致程序的分段错误和终止。
大多数系统都没有以安全为中心的OpenBSD系统,虽然。
知道了这一点,当我编码具有对大量内存的已知将要暂时需求的长期运行的系统,我总是试图fork
过程:那么父母只是等待结果从孩子[ [典型地在管道上],孩子不计算(包括存储器分配),返回结果[[上所述管],然后终止。 这样一来,我的长期运行的进程不会在其内存需求偶然的“尖峰”之间的长期时期白白占用内存。 其他替代策略包括切换到自定义的内存分配器这样的特殊要求(C ++使得它相当容易,但这样的下方的虚拟机为Java和Python语言通常不)。
我处理同样的问题的任择议定书。 到目前为止,似乎有可能与tcmalloc。 我发现了两个解决方案:
与tcmalloc链接编译你的程序,然后启动它:
env TCMALLOC_RELEASE=100 ./my_pthread_soft
文件提到,
合理的价格的范围是[0,10]。
但10似乎并不足够,我(即我看不出有什么变化)。
找个地方在你的代码中这将是有趣释放所有释放的内存,然后添加以下代码:
#include "google/malloc_extension_c.h" // C include #include "google/malloc_extension.h" // C++ include /* ... */ MallocExtension_ReleaseFreeMemory();
第二个解决方案已经在我的情况非常有效; 第一个将是巨大的,但不是很成功的,它是复杂的发现,例如正确的号码。
对于所有“正常” mallocs,包括你提到的那些,内存被释放到你的过程中重复使用,但不回整个系统。 释放回整个系统只有当您处理最后终止的影响。
你列出的那些中,只有囤将返回内存的系统...但如果它实际上可以做到这一点,将取决于你的程序的分配行为很多。
我在我的应用程序也有类似的问题,经过一番调查,我注意到,由于某种原因glibc不返回的内存时分配的对象是小的(在我的情况小于120个字节)的系统。
看看下面的代码:
#include <list>
#include <malloc.h>
template<size_t s> class x{char x[s];};
int main(int argc,char** argv){
typedef x<100> X;
std::list<X> lx;
for(size_t i = 0; i < 500000;++i){
lx.push_back(X());
}
lx.clear();
malloc_stats();
return 0;
}
程序的输出:
Arena 0:
system bytes = 64069632
in use bytes = 0
Total (incl. mmap):
system bytes = 64069632
in use bytes = 0
max mmap regions = 0
max mmap bytes = 0
约64 MB不返回系统。 当我改变的typedef: typedef x<110> X;
程序输出如下:
Arena 0:
system bytes = 135168
in use bytes = 0
Total (incl. mmap):
system bytes = 135168
in use bytes = 0
max mmap regions = 0
max mmap bytes = 0
几乎所有的内存被释放。 我还注意到,使用malloc_trim(0)
在任一情况下释放的存储器系统。
下面是添加后输出malloc_trim
到上面的代码:
Arena 0:
system bytes = 4096
in use bytes = 0
Total (incl. mmap):
system bytes = 4096
in use bytes = 0
max mmap regions = 0
max mmap bytes = 0
答案很简单:要强制malloc子系统内存返回到操作系统,使用malloc_trim()。 否则,返回内存的行为是依赖于实现的。