mic*_*ael 5 linux malloc free glibc
我目前正在处理的一些程序消耗的内存比我想象的要多得多.所以我想了解glibc malloc修剪是如何工作的.我写了以下测试:
#include <malloc.h>
#include <unistd.h>
#define NUM_CHUNKS 1000000
#define CHUNCK_SIZE 100
int main()
{
// disable fast bins
mallopt(M_MXFAST, 0);
void** array = (void**)malloc(sizeof(void*) * NUM_CHUNKS);
// allocating memory
for(unsigned int i = 0; i < NUM_CHUNKS; i++)
{
array[i] = malloc(CHUNCK_SIZE);
}
// releasing memory ALMOST all memory
for(unsigned int i = 0; i < NUM_CHUNKS - 1 ; i++)
{
free(array[i]);
}
// when enabled memory consumption reduces
//int ret = malloc_trim(0);
//printf("ret=%d\n", ret);
malloc_stats();
sleep(100000);
}
Run Code Online (Sandbox Code Playgroud)
测试输出(不调用malloc_trim):
Arena 0:
system bytes = 112054272
in use bytes = 112
Total (incl. mmap):
system bytes = 120057856
in use bytes = 8003696
max mmap regions = 1
max mmap bytes = 8003584
Run Code Online (Sandbox Code Playgroud)
尽管几乎所有内存都已发布,但此测试代码消耗的驻留内存比预期多得多:
[root@node0-b3]# ps aux | grep test
root 14662 1.8 0.4 129736 **118024** pts/10 S 20:19 0:00 ./test
Run Code Online (Sandbox Code Playgroud)
处理粉碎:
0245e000-08f3b000 rw-p 00000000 00:00 0 [heap]
Size: 109428 kB
Rss: 109376 kB
Pss: 109376 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 109376 kB
Referenced: 109376 kB
Anonymous: 109376 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac
7f1c60720000-7f1c60ec2000 rw-p 00000000 00:00 0
Size: 7816 kB
Rss: 7816 kB
Pss: 7816 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 7816 kB
Referenced: 7816 kB
Anonymous: 7816 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
Run Code Online (Sandbox Code Playgroud)
当我启用对malloc_trim的调用时,测试的输出几乎保持不变:
ret=1
Arena 0:
system bytes = 112001024
in use bytes = 112
Total (incl. mmap):
system bytes = 120004608
in use bytes = 8003696
max mmap regions = 1
max mmap bytes = 8003584
Run Code Online (Sandbox Code Playgroud)
但是,RSS显着下降:
[root@node0-b3]# ps aux | grep test
root 15733 0.6 0.0 129688 **8804** pts/10 S 20:20 0:00 ./test
Run Code Online (Sandbox Code Playgroud)
处理smaps(在malloc_trim之后):
01698000-08168000 rw-p 00000000 00:00 0 [heap]
Size: 109376 kB
Rss: 8 kB
Pss: 8 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 8 kB
Referenced: 8 kB
Anonymous: 8 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac
7f508122a000-7f50819cc000 rw-p 00000000 00:00 0
Size: 7816 kB
Rss: 7816 kB
Pss: 7816 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 7816 kB
Referenced: 7816 kB
Anonymous: 7816 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
Run Code Online (Sandbox Code Playgroud)
在调用malloc_trim之后,堆被破坏了.我假设8MB mmap段仍然可用,因为最后一块内存未发布.
为什么malloc不会自动执行堆修剪?有没有办法配置malloc,以便自动完成修剪(何时可以节省大量内存)?
我使用的是glibc 2.17版.
很大程度上由于历史原因,小分配的内存来自由brk系统调用管理的池。这是一个非常古老的系统调用——至少与版本 6 Unix一样古老 ——它唯一能做的就是改变一个在内存中位置固定的“arena”的大小。这意味着,brk池不能收缩超过仍然分配的块。
您的程序分配 N 个内存块,然后释放其中的 N-1 个。它不释放的块是位于最高地址的块。这是最坏的情况brk:即使池的 99.99% 未使用,也根本无法减小大小!如果你改变你的程序,以便它不会释放块是array[0]不是array[NUM_CHUNKS-1],你应该看到在到最后调用RSS和地址空间收缩free。
当您显式调用 时malloc_trim,它会尝试使用 Linux 扩展来解决此限制madvise(MADV_DONTNEED), 释放物理 RAM,但不释放地址空间(如您所见)。我不知道为什么这只发生在显式调用malloc_trim.
顺便说一句,8MB mmap 段用于您最初分配的array.
| 归档时间: |
|
| 查看次数: |
1510 次 |
| 最近记录: |