我有一个使用频繁内存分配-释放的长寿命应用程序。是否会有任何malloc
实现将释放的内存返回给系统?
在这方面,什么是行为:
google threaded malloc)
更新
如果我有一个应用程序,它的内存消耗在白天和晚上可能有很大的不同(例如),我可以强制任何malloc
将释放的内存返回给系统吗?
如果没有这样的返回,释放的内存将被多次换出和换入,但这样的内存只包含垃圾。
发布于 2010-10-05 10:35:58
以下分析仅适用于glibc (基于ptmalloc2
算法)。有一些选项似乎对将释放的内存返回系统很有帮助:
malloc.h
中定义)提供了使用参数选项M_TRIM_THRESHOLD
之一设置修剪阈值的选项,这表示数据段顶部允许的最小可用内存量(以字节为单位)。如果内存数量低于这个阈值,则glibc会调用brk()
将内存回馈给内核。在Linux中,M_TRIM_THRESHOLD
的默认值被设置为128K,设置一个较小的值可能会节省空间。
可以通过在环境变量MALLOC_TRIM_THRESHOLD_
中设置修剪阈值来实现相同的行为,而完全不需要更改源代码。
然而,使用M_TRIM_THRESHOLD
运行的初步测试程序表明,即使malloc
分配的内存确实返回到系统,最初通过brk()
请求的实际内存块(竞技场)的剩余部分往往会被保留。
malloc_trim(pad)
(在malloc.h
中定义)来裁剪内存区域并将任何未使用的内存返回给系统。此函数调整数据段的大小,在其末尾保留至少pad
个字节,如果可释放的字节少于一页,则会失败。段大小始终是一页的倍数,在i386上为4,096字节。使用malloc_trim
实现这种修改后的free()
行为可以使用malloc钩子功能来完成。这将不需要对核心glibc库进行任何源代码更改。
glibc
.中使用
madvise()
系统调用的免费实现发布于 2010-02-07 08:26:20
大多数实现都不会去识别那些(相对少见的)整个“块”(无论大小适合操作系统)已被释放并可以返回的情况,但当然也有例外。例如,我引用了the wikipedia page在OpenBSD中的话:
在调用
free
时,使用munmap释放内存并从进程地址空间取消映射。该系统旨在通过利用OpenBSD的mmap
系统调用中实现的地址空间布局随机化和gap页功能来提高安全性,并检测释放后使用的错误-由于大量内存分配在释放后完全未映射,进一步使用会导致分段错误和程序终止。
不过,大多数系统并不像OpenBSD那样以安全为中心。
知道这一点,当我编写一个长时间运行的系统,它有一个已知的对大量内存的暂时需求时,我总是尝试fork
进程:然后父进程只是等待来自子进程的结果(通常在管道上),子进程进行计算(包括内存分配),返回结果(在所述管道上),然后终止。这样,我的长时间运行的进程将不会在其内存需求的偶尔“峰值”之间的较长时间内无用地占用内存。其他替代策略包括针对此类特殊需求切换到自定义内存分配器(C++使其变得相当简单,尽管底层是虚拟机的语言通常不会)。
发布于 2013-12-16 02:45:00
我在我的应用程序中遇到了类似的问题,经过一些调查后,我注意到,由于某种原因,当分配的对象很小(在我的例子中小于120字节)时,glibc不会向系统返回内存。
看看这段代码:
#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 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
https://stackoverflow.com/questions/2215259
复制相似问题