强制 free() 将 malloc 内存返回给操作系统 [英] Force free() to return malloc memory back to OS
问题描述
似乎即使在我释放了由 malloc()
分配的 Linux 进程的所有内存之后,内存仍为进程保留,不会返回给操作系统.
Seems like even after I free all the memory for a Linux process that was allocated by malloc()
,
memory is still reserved for the process and not returned to the OS.
默认运行 valgrind massif
工具显示没有泄漏.
Running valgrind massif
tool by default reveals no leakages.
使用 --pages-as-heap=yes
运行 valgrind
揭示了这一点:
Running valgrind
with --pages-as-heap=yes
reveals this:
->13.77% (7,655,424B) 0x35FEEEB069:brk (brk.c:31)
->13.77% (7,655,424B) 0x35FEEEB069: brk (brk.c:31)
->13.77% (7,655,424B) 0x35FEEEB113:sbrk (sbrk.c:53)
->13.77% (7,655,424B) 0x35FEEEB113: sbrk (sbrk.c:53)
->13.77% (7,655,424B) 0x35FEE82717:__default_morecore (morecore.c:48)
->13.77% (7,655,424B) 0x35FEE82717: __default_morecore (morecore.c:48)
->13.77% (7,655,424B) 0x35FEE7DCCB: _int_malloc (malloc.c:2455)
->13.77% (7,655,424B) 0x35FEE7DCCB: _int_malloc (malloc.c:2455)
->13.77% (7,655,424B) 0x35FEE7F4F1:malloc (malloc.c:2862)
->13.77% (7,655,424B) 0x35FEE7F4F1: malloc (malloc.c:2862)
所以即使 free()
已经释放了内存,似乎 malloc
调用了 brk/sbrk
并且没有将它返回给操作系统.
so even though memory was already freed by free()
, it seems that malloc
called brk/sbrk
and did not return this to the OS.
如何强制 free()
立即调用 sbrk()
并将所有内存返回给操作系统?
how can I force free()
to call sbrk()
immediately and return all memory back to the OS ?
我在一个非常低端的平台上运行,每 MB 都很重要.
I am running on a very low end platform which every MB counts.
提前致谢.
推荐答案
用 glibc malloc 尝试调用 malloc_trim
函数.它没有详细记录,并且在 2007 年左右(glibc 2.9)内部发生了变化 - https://stackoverflow.com/a/42281428一>.
With glibc malloc try to call malloc_trim
function. It is not well documented and there were changes inside it at around 2007 (glibc 2.9) - https://stackoverflow.com/a/42281428.
自 2007 年以来,此函数将: 遍历所有 malloc 内存区域(用于多线程应用程序),执行修剪和 fastbin 合并;并释放完全释放的所有对齐 (4KB) 页面.
Since 2007 this function will: Iterate over all malloc memory arenas (used in multithreaded applications) doing trim and fastbin consolidation; and release all aligned (4KB) pages fully freed.
乌尔里希·德雷珀2007 年 12 月 16 日,星期日 22:53:08 +0000 (22:53 +0000)
Ulrich Drepper Sun, 16 Dec 2007 22:53:08 +0000 (22:53 +0000)
- malloc/malloc.c (public_mTRIm):遍历所有领域并为所有领域调用 mTRIm.
(mTRIm):另外迭代所有空闲块并使用 madvise为所有包含至少一个的块释放内存内存页.
(mTRIm): Additionally iterate over all free blocks and use madvise to free memory for all those blocks which contain at least one memory page.
+ 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 进行 madvised 时,操作系统可能会取消映射或不取消映射物理页面,而 linux 通常会取消映射.madvised 页面仍然计入 VSIZE(进程的总虚拟内存大小),但通常有助于减少 RSS(进程使用的物理内存量).
So, calling malloc_trim
will release almost all freed memory back to the OS. Only pages containing still not freed data will be kept; OS may unmap or not unmap physical page when madvised with MADV_DONTNEED and linux usually does unmap. madvised pages are still count to VSIZE (total virtual memory size of the process), but usually help to reduce RSS (amount of physical memory used by process).
或者,您可以尝试切换到替代 malloc 库:tcmalloc (gperftools/google-perftools) 或 jemalloc (facebook),它们都有将释放的内存返回给操作系统的激进规则(使用 madvise MADV_DONTNEED 甚至
Alternatively, you can try to switch into alternative malloc library: tcmalloc (gperftools / google-perftools) or jemalloc (facebook), both of them have aggressive rules of returning freed memory back to OS (with madvise MADV_DONTNEED or even MADV_FREE).
这篇关于强制 free() 将 malloc 内存返回给操作系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!