linux – 了解glibc malloc修剪
我目前正在处理的一些程序消耗的内存比我想象的要多得多.所以我想了解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=%dn",ret); malloc_stats(); sleep(100000); } 测试输出(不调用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 尽管几乎所有内存都已发布,但此测试代码消耗的驻留内存比预期多得多: [root@node0-b3]# ps aux | grep test root 14662 1.8 0.4 129736 **118024** pts/10 S 20:19 0:00 ./test 处理粉碎: 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 当我启用对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 但是,RSS显着下降: [root@node0-b3]# ps aux | grep test root 15733 0.6 0.0 129688 **8804** pts/10 S 20:20 0:00 ./test 处理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 在调用malloc_trim之后,堆被破坏了.我假设8MB mmap段仍然可用,因为最后一块内存未发布. 为什么malloc不会自动执行堆修剪? 我使用的是glibc 2.17版. 解决方法
主要由于历史原因,小分配的内存来自使用
brk 系统调用管理的池.这是一个非常古老的系统调用 – 至少与
Version 6 Unix一样久 – 它唯一能做的就是改变在内存中的位置是固定的“竞技场”的大小.这意味着,brk池不能缩小到仍然分配的块.
您的程序分配N个内存块,然后释放N-1个内存.它没有解除分配的一个块是位于最高地址的块.对于brk来说,这是最糟糕的情况:即使99.99%的游泳池未被使用,也无法减小尺寸!如果您更改程序以使其不释放的块是数组[0]而不是数组[NUM_CHUNKS-1],您应该看到RSS和地址空间在最终调用free时缩小. 当您显式调用malloc_trim时,它会尝试使用Linux扩展 顺便提一下,8MB mmap段用于初始分配数组. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |