将malloc实现恢复自由版内存回系统?将malloc实现恢复自由版内存回系统?(Will mall

2019-05-09 02:07发布

我有频繁的内存分配,释放长期生活应用。 将所有的malloc实现回报释放的内存回系统?

是什么,在这方面,的行为:

  • ptmalloc 1,2(glibc的默认值)或3
  • dlmalloc
  • tcmalloc(谷歌螺纹的malloc)
  • 在solaris 10-11默认的malloc和为mtmalloc
  • FreeBSD的8默认的malloc(jemalloc)
  • 囤积居奇的malloc?

更新

如果我有一个应用程序,它的内存消耗可以在白天和夜间(例如)非常不同,我可以强制任何的malloc的到释放的内存返回到系统?

如果没有这样的回报率释放的内存将被换出,并在很多次,但这种记忆只包含垃圾。

Answer 1:

以下分析仅适用于glibc的(基于ptmalloc2算法)。 有迹象表明,似乎有助于回返回释放的内存给系统的某些选项:

  1. mallopt() (定义在malloc.h )不提供一个选项来设置使用参数选项之一修剪阈值M_TRIM_THRESHOLD ,这指示允许在该数据段的顶部的自由存储器(以字节计)的最小量。 如果量低于这个阈值,glibc的调用brk()来回馈内存的内核。

    默认值M_TRIM_THRESHOLD在Linux中设置为128K,设置较小的值可能节省空间。

    同样的行为可以通过在环境变量设置微调阈值来实现MALLOC_TRIM_THRESHOLD_ ,完全没有来源的变化。

    然而,初步试验程序的运行使用M_TRIM_THRESHOLD表明即使由malloc的分配的内存并返回到系统中,存储器(竞技场)通过最初所请求的实际数据块的剩余部分brk()趋向于被保留。

  2. 是可能的修剪存储器舞台,并通过调用给任何未使用的存储器回系统malloc_trim(pad) (定义在malloc.h )。 该功能调整大小的数据段,留下至少pad在它的结束字节,如果失败的字节少于一个页面值得可以被释放。 段大小始终是一个网页,这是在i386上4096个字节的倍数。

    对于这个修改行为的实现free()使用malloc_trim可以使用malloc的钩功能来完成。 这不需要任何修改源代码的核心glibc库。

  3. 使用madvise()的免费实现的glibc的内部系统调用。



Answer 2:

大多数的实现不打扰查明整个“块”(无论大小适合OS)已被释放,并可能会返回那些(比较少见)的情况下,但也有例外当然的。 例如,我从引用维基百科页面 ,在OpenBSD的:

在一个通话free ,内存被释放,并使用munmap从进程的地址空间解除映射。 这一制度旨在通过利用作为OpenBSD的一部分实施的地址空间布局随机化和差距页面的功能优势,以提高安全性mmap系统调用,并检测释放后使用无漏洞,作为一个大的内存分配是完全映射的是后中解脱出来,进一步使用导致程序的分段错误和终止。

大多数系统都没有以安全为中心的OpenBSD系统,虽然。

知道了这一点,当我编码具有对大量内存的已知将要暂时需求的长期运行的系统,我总是试图fork过程:那么父母只是等待结果从孩子[ [典型地在管道上],孩子不计算(包括存储器分配),返回结果[[上所述管],然后终止。 这样一来,我的长期运行的进程不会在其内存需求偶然的“尖峰”之间的长期时期白白占用内存。 其他替代策略包括切换到自定义的内存分配器这样的特殊要求(C ++使得它相当容易,但这样的下方的虚拟机为Java和Python语言通常不)。



Answer 3:

我处理同样的问题的任择议定书。 到目前为止,似乎有可能与tcmalloc。 我发现了两个解决方案:

  1. 与tcmalloc链接编译你的程序,然后启动它:

     env TCMALLOC_RELEASE=100 ./my_pthread_soft 

    文件提到,

    合理的价格的范围是[0,10]。

    但10似乎并不足够,我(即我看不出有什么变化)。

  2. 找个地方在你的代码中这将是有趣释放所有释放的内存,然后添加以下代码:

     #include "google/malloc_extension_c.h" // C include #include "google/malloc_extension.h" // C++ include /* ... */ MallocExtension_ReleaseFreeMemory(); 

第二个解决方案已经在我的情况非常有效; 第一个将是巨大的,但不是很成功的,它是复杂的发现,例如正确的号码。



Answer 4:

对于所有“正常” mallocs,包括你提到的那些,内存被释放到你的过程中重复使用,但不回整个系统。 释放回整个系统只有当您处理最后终止的影响。



Answer 5:

你列出的那些中,只有囤将返回内存的系统...但如果它实际上可以做到这一点,将取决于你的程序的分配行为很多。



Answer 6:

我在我的应用程序也有类似的问题,经过一番调查,我注意到,由于某种原因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


Answer 7:

答案很简单:要强制malloc子系统内存返回到操作系统,使用malloc_trim()。 否则,返回内存的行为是依赖于实现的。



文章来源: Will malloc implementations return free-ed memory back to the system?