Einige Programme, an denen ich gerade arbeite, verbrauchen viel mehr Speicher als ich denke, es sollte. Also versuche ich zu verstehen, wie glibc malloc trimming funktioniert. Ich schrieb den folgenden Test:Verstehen glibc malloc trimmen
#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);
}
Testausgang (ohne malloc_trim Aufruf):
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
Obwohl fast alle Speicher freigegeben wurde, dieser Test Code verbraucht viel mehr residenten Speicher als erwartet:
[[email protected]]# ps aux | grep test
root 14662 1.8 0.4 129736 **118024** pts/10 S 20:19 0:00 ./test
Prozess 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
Wenn ich ermöglichen den Aufruf den Ausgang des Tests malloc_trim fast gleich bleibt:
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
jedoch die RSS deutlich verringert:
[[email protected]]# ps aux | grep test
root 15733 0.6 0.0 129688 **8804** pts/10 S 20:20 0:00 ./test
Prozess smaps (nach 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
Nach dem Aufruf von malloc_trim wurde der Heap durchsucht. Ich nehme an, dass das 8MB-mmap-Segment immer noch verfügbar ist, weil das letzte Stück Speicher nicht freigegeben wurde.
Warum Heap-Trimmen wird nicht automatisch von malloc durchgeführt? Gibt es eine Möglichkeit, malloc so zu konfigurieren, dass das Trimmen automatisch durchgeführt wird (wenn so viel Speicher gespart werden kann)?
Ich verwende Glibc Version 2.17.
Wenn Sie viel Speicher verwenden und auf besondere Weise behandelt werden müssen, empfehle ich, dies selbst zu tun, indem Sie "mmap" unter POSIX und "VirtualAlloc" unter Windows verwenden. –