使用 glibc malloc 尝试调用malloc_trim
功能。它没有很好的文档记录,并且在 2007 年左右进行了内部更改(glibc 2.9) -https://stackoverflow.com/a/42281428.
自 2007 年以来,该函数将: 迭代所有 malloc 内存区域(在多线程应用程序中使用),进行修剪和 fastbin 整合;并完全释放所有对齐的 (4KB) 页。
https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc
乌尔里希·德雷珀
2007 年 12 月 16 日星期日 22:53:08 +0000 (22:53 +0000)
- malloc/malloc.c (public_mTRIm):迭代所有 arena 并为所有 arena 调用 mTRIm。
(mTRIm):另外迭代所有空闲块并使用 madvise
为所有包含至少一个的块释放内存
内存页。
https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=malloc/malloc.c;h=c54c203cbf1f024e72493546221305b4fd5729b7;hp=1e716089a2b976d120c304ad75dd95c63737ad75;hb=68 631c8eb92ff38d9da1ae34f6aa048539b199cc;hpb=52386be756e113f20502f181d780aecc38cbb66a
+ malloc_consolidate (av);
...
+ for (int i = 1; i < NBINS; ++i)
...
+ for (mchunkptr p = last (bin); p != bin; p = p->bk)
+ {
...
+ /* See whether the chunk contains at least one unused page. */
+ char *paligned_mem = (char *) (((uintptr_t) p
+ + sizeof (struct malloc_chunk)
+ + psm1) & ~psm1);
...
+ /* This is the size we could potentially free. */
+ size -= paligned_mem - (char *) p;
+
+ if (size > psm1)
+ {
...
+ madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);
所以,打电话malloc_trim
将释放几乎所有已释放的内存回操作系统。仅保留包含尚未释放数据的页面;当使用 MADV_DONTNEED 疯狂时,操作系统可能会取消映射或不取消映射物理页,而 linux 通常会取消映射。 madvised 页面仍然计入 VSIZE(进程的总虚拟内存大小),但通常有助于减少 RSS(进程使用的物理内存量)。
或者,您可以尝试切换到替代的 malloc 库:tcmalloc (gperftools / google-perftools) 或 jemalloc (facebook),它们都具有将释放的内存返回到操作系统的积极规则(使用 madvise MADV_DONTNEED 甚至MADV_FREE).