强制 free() 到 return malloc 内存回到 OS
Force free() to return malloc memory back to OS
似乎即使在我为 malloc()
分配的 Linux 进程释放所有内存之后,
内存仍然保留给进程,而不是 returned 到 OS.
运行 valgrind massif
工具默认显示无泄漏。
运行 valgrind
和 --pages-as-heap=yes
揭示了这一点:
->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) 0x35FEE82717: __default_morecore (morecore.c:48)
->13.77% (7,655,424B) 0x35FEE7DCCB: _int_malloc (malloc.c:2455)
->13.77% (7,655,424B) 0x35FEE7F4F1: malloc (malloc.c:2862)
所以即使内存已经被 free()
释放,似乎 malloc
调用了 brk/sbrk
而没有 return 调用 OS。
如何强制 free()
立即调用 sbrk()
并将 return 所有内存返回给 OS?
我 运行 在非常低端的平台上,每个 MB 都很重要。
提前致谢。
让 OS 回收内存的唯一可靠且便携的方法是 退出进程 并重新启动它,恢复您需要继续的任何状态。
当然,根据您的需要使用 brk/sbrk 编写您自己的 malloc/free 实现是另一种选择。
使用 glibc malloc 尝试调用 malloc_trim
函数。它没有很好的记录,并且在 2007 年左右 (glibc 2.9) 内部发生了变化 - .
自 2007 年以来,此功能将: 遍历所有 malloc 内存区域(用于多线程应用程序)进行 trim 和 fastbin 合并;并完全释放所有对齐的 (4KB) 页面。
Ulrich Drepper
Sun, 16 Dec 2007 22:53:08 +0000 (22:53 +0000)
- malloc/malloc.c (public_mTRIm): Iterate over all arenas and call mTRIm for all of them.
(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
会将几乎所有释放的内存释放回 OS。仅保留包含尚未释放数据的页面;当使用 MADV_DONTNEED 时,OS 可能取消映射或不取消映射物理页面,而 linux 通常取消映射。疯狂的页面仍然计入 VSIZE(进程的总虚拟内存大小),但通常有助于减少 RSS(进程使用的物理内存量)。
或者,您可以尝试切换到替代 malloc 库:tcmalloc (gperftools / google-perftools) 或 jemalloc (facebook),它们都有将释放的内存返回到 [=34 的积极规则=](使用 madvise MADV_DONTNEED 甚至 MADV_FREE)。
似乎即使在我为 malloc()
分配的 Linux 进程释放所有内存之后,
内存仍然保留给进程,而不是 returned 到 OS.
运行 valgrind massif
工具默认显示无泄漏。
运行 valgrind
和 --pages-as-heap=yes
揭示了这一点:
->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) 0x35FEE82717: __default_morecore (morecore.c:48)
->13.77% (7,655,424B) 0x35FEE7DCCB: _int_malloc (malloc.c:2455)
->13.77% (7,655,424B) 0x35FEE7F4F1: malloc (malloc.c:2862)
所以即使内存已经被 free()
释放,似乎 malloc
调用了 brk/sbrk
而没有 return 调用 OS。
如何强制 free()
立即调用 sbrk()
并将 return 所有内存返回给 OS?
我 运行 在非常低端的平台上,每个 MB 都很重要。
提前致谢。
让 OS 回收内存的唯一可靠且便携的方法是 退出进程 并重新启动它,恢复您需要继续的任何状态。
当然,根据您的需要使用 brk/sbrk 编写您自己的 malloc/free 实现是另一种选择。
使用 glibc malloc 尝试调用 malloc_trim
函数。它没有很好的记录,并且在 2007 年左右 (glibc 2.9) 内部发生了变化 -
自 2007 年以来,此功能将: 遍历所有 malloc 内存区域(用于多线程应用程序)进行 trim 和 fastbin 合并;并完全释放所有对齐的 (4KB) 页面。
Ulrich Drepper Sun, 16 Dec 2007 22:53:08 +0000 (22:53 +0000)
- malloc/malloc.c (public_mTRIm): Iterate over all arenas and call mTRIm for all of them.
(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
会将几乎所有释放的内存释放回 OS。仅保留包含尚未释放数据的页面;当使用 MADV_DONTNEED 时,OS 可能取消映射或不取消映射物理页面,而 linux 通常取消映射。疯狂的页面仍然计入 VSIZE(进程的总虚拟内存大小),但通常有助于减少 RSS(进程使用的物理内存量)。
或者,您可以尝试切换到替代 malloc 库:tcmalloc (gperftools / google-perftools) 或 jemalloc (facebook),它们都有将释放的内存返回到 [=34 的积极规则=](使用 madvise MADV_DONTNEED 甚至 MADV_FREE)。