首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解glibc malloc修剪

理解glibc malloc修剪
EN

Stack Overflow用户
提问于 2016-07-28 18:54:09
回答 1查看 3.4K关注 0票数 6

我目前正在开发的一些程序消耗的内存比我认为的要多。所以我试着去了解glibc malloc修剪是如何工作的。我编写了以下测试:

代码语言:javascript
复制
#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);
}

测试输出(不调用malloc_trim):

代码语言:javascript
复制
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

尽管几乎所有内存都已释放,但此测试代码消耗的驻留内存比预期的要多得多:

代码语言:javascript
复制
[root@node0-b3]# ps aux | grep test
root     14662  1.8  0.4 129736 **118024** pts/10  S    20:19   0:00 ./test

过程击打:

代码语言:javascript
复制
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的调用时,测试的输出几乎保持不变:

代码语言:javascript
复制
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显著减少:

代码语言:javascript
复制
[root@node0-b3]# ps aux | grep test
root     15733  0.6  0.0 129688  **8804** pts/10   S    20:20   0:00 ./test

Process (在malloc_trim之后):

代码语言:javascript
复制
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自动执行的?是否有一种方法可以配置malloc,以便自动完成裁剪(当它可以节省那么多内存时)?

我使用的是glibc版本2.17。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-28 19:12:33

主要是由于历史原因,用于小分配的内存来自使用brk系统调用管理的池。这是一个非常古老的系统调用--至少和版本6 Unix一样古老--它唯一能做的就是改变内存位置固定的“竞技场”的大小。这意味着,brk池不能缩小超过仍在分配的块。

您的程序分配N个内存块,然后释放其中的N1。它没有释放的一个块是位于最高地址的块。这是brk最坏的情况:即使99.99%的池未使用,也无法缩小其大小!如果您更改您的程序,使它不能释放的块是array[0]而不是array[NUM_CHUNKS-1],那么在对free的最后调用时,您应该会看到RSS和地址空间都缩小了。

当您显式调用malloc_trim时,它尝试使用madvise(MADV_DONTNEED)扩展来解决这个限制,它释放物理内存,但不释放地址空间(正如您所观察到的)。我不知道为什么只有在明确调用malloc_trim时才会发生这种情况。

顺便说一句,8MB的mmap段用于您最初的array分配。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38644578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档