2016-07-28 3 views
5

현재 작업하고있는 일부 프로그램은 생각보다 훨씬 많은 메모리를 사용합니다. 그래서 glibc malloc 트리밍이 어떻게 작동하는지 이해하려고합니다.glibc malloc 트리밍 이해

:

거의 모든 메모리가 해제되었다하더라도
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 

는이 테스트 코드는 예상보다 훨씬 더 많은 상주 메모리를 소모 : (malloc_trim를 호출하지 않고)

#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); 
} 

시험 출력 : I는 다음의 시험을 썼다

[[email protected]]# ps aux | grep test 
root  14662 1.8 0.4 129736 **118024** pts/10 S 20:19 0:00 ./test 

프로세스 현재 smaps :

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는 크게 감소 :

[[email protected]]# 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을 호출 한 후 힙이 shunk되었습니다. 나는 8MB mmap 세그먼트가 출시되지 않은 마지막 메모리 때문에 여전히 사용 가능하다고 가정합니다.

malloc에서 힙 트리밍을 자동으로 수행하지 않는 이유는 무엇입니까? 트리밍이 자동으로 수행되도록 malloc을 구성하는 방법이 있습니까 (많은 메모리를 절약 할 수있을 때)?

glibc 버전 2.17을 사용하고 있습니다.

+0

많은 메모리를 사용하고 있으며 특별한 방법으로 처리해야하는 경우 POSIX에서는'mmap'을, Windows에서는'VirtualAlloc'을 사용하여 직접 처리하는 것이 좋습니다. –

답변

4

일반적으로 역사적인 이유로 작은 할당을위한 메모리는 brk 시스템 호출로 관리되는 풀에서 가져옵니다. 이것은 적어도 아주 오래된 시스템 호출입니다. 최소한 Version 6 Unix만큼 오래되었습니다. 수행 할 수있는 유일한 것은 크기가 메모리의 위치가 고정 된 "경기장"의입니다. 즉, brk 풀은 할당 된 블록을 지나쳐 축소 할 수 없습니다.

프로그램은 N 개의 메모리 블록을 할당 한 다음 N-1 개의 메모리를 할당 해제합니다. 할당을 해제하지 않은 한 블록은 주소 인 주소에 있습니다. brk에 대한 최악의 시나리오는 풀의 99.99 %가 사용되지 않더라도 크기를 전혀 줄일 수 없다는 것입니다. 해제 할 블록이 array[NUM_CHUNKS-1] 대신 array[0]이되도록 프로그램을 변경하면 free으로 최종 호출 할 때 RSS와 주소 공간이 모두 축소됩니다.

명시 적으로 malloc_trim을 호출하면 실제로 주소가 아닌 실제 RAM을 해제하는 Linux 확장명 인 madvise(MADV_DONTNEED)을 사용하여이 제한을 해결하려고합니다 (관찰 한대로). 나는 이것이 왜 malloc_trim에 대한 명백한 호출에서만 일어나는 지 모른다.

덧붙여서, 8MB mmap 세그먼트는 초기 할당 array입니다.

+0

답변 해 주셔서 감사합니다. 'array'는 실제로 8MB 세그먼트에 있고, 배열 [N-1]은 힙 세그먼트의 ** end **에 위치한다는 것을 알았습니다. 그것의 끝 부분에 있다면, 지금은 (malloc_trim을 호출 할 때) 그것이 어떻게 다듬을 수 있는지 이해하지 못한다. – michael

+0

다시 'madvise'에 대해 내가 말한 것을 읽으십시오 ... – zwol

+0

고맙습니다. RSS 메모리 사용량을 줄이는 방법이 있습니까? 'malloc_trim'을 매번 호출하는 것 외에는? – michael