pagina
Man of malloc_trim
sono stati impegnati qui: https://github.com/mkerrisk/man-pages/blob/master/man3/malloc_trim.3 e, come ho capito, è stato scritto da man-pages di progetto manutentore, kerrisk nel 2012 da zero: https://github.com/mkerrisk/man-pages/commit/a15b0e60b297e29c825b7417582a33e6ca26bf65
Come posso grep the glibc's git, there are no man pages in the glibc, e non si impegnano a pagina man malloc_trim per documentare questa patch. La documentazione migliore e l'unico di malloc glibc è il suo codice sorgente: https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c Non ci sono commenti da malloc_trim
malloc/malloc.c
:
Additional functions:
malloc_trim(size_t pad);
609 /*
610 malloc_trim(size_t pad);
611
612 If possible, gives memory back to the system (via negative
613 arguments to sbrk) if there is unused memory at the `high' end of
614 the malloc pool. You can call this after freeing large blocks of
615 memory to potentially reduce the system-level memory requirements
616 of a program. However, it cannot guarantee to reduce memory. Under
617 some allocation patterns, some large free blocks of memory will be
618 locked between two used chunks, so they cannot be given back to
619 the system.
620
621 The `pad' argument to malloc_trim represents the amount of free
622 trailing space to leave untrimmed. If this argument is zero,
623 only the minimum amount of memory to maintain internal data
624 structures will be left (one page or less). Non-zero arguments
625 can be supplied to maintain enough trailing space to service
626 future expected allocations without having to re-obtain memory
627 from the system.
628
629 Malloc_trim returns 1 if it actually released any memory, else 0.
630 On systems that do not support "negative sbrks", it will always
631 return 0.
632 */
633 int __malloc_trim(size_t);
634
liberarsi dalla metà del pezzo non è documentato come testo in malloc/malloc.c e non documentato nel progetto man-pages. La pagina man del 2012 potrebbe essere la prima pagina man della funzione, scritta non dagli autori di glibc. La pagina delle informazioni di glibc menziona solo M_TRIM_THRESHOLD di 128 KB: https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html#Malloc-Tunable-Parameters e non elenca la funzione malloc_trim https://www.gnu.org/software/libc/manual/html_node/Summary-of-Malloc.html#Summary-of-Malloc (e inoltre non documenta memusage/memusagestat/libmemusage.so).
Nel dicembre 2007 è stato eseguito il commit https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc da Ulrich Drepper (fa parte di glibc 2.9 e successive) che ha cambiato mtrim
applicazione (ma non ha cambiato alcuna documentazione o man page come non ci sono le pagine man in glibc):
- malloc/malloc.c (public_mTRIm): iterare su tutto arene e chiamare
mTRIm per tutti loro. (mTRIm): Ulteriore iterare su tutti i blocchi liberi e utilizzare madvise per liberare memoria per tutti quei blocchi che contengono almeno una pagina di memoria .
parti inutilizzate dei pezzi (ovunque, anche pezzi in mezzo), adeguata alla dimensione della pagina e aventi dimensioni più di pagina può essere contrassegnato come MADV_DONTNEED
https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=malloc/malloc.c;h=c54c203cbf1f024e72493546221305b4fd5729b7;hp=1e716089a2b976d120c304ad75dd95c63737ad75;hb=68631c8eb92ff38d9da1ae34f6aa048539b199cc;hpb=52386be756e113f20502f181d780aecc38cbb66a
INTERNAL_SIZE_T size = chunksize (p);
if (size > psm1 + sizeof (struct malloc_chunk))
{
/* See whether the chunk contains at least one unused page. */
char *paligned_mem = (char *) (((uintptr_t) p
+ sizeof (struct malloc_chunk)
+ psm1) & ~psm1);
assert ((char *) chunk2mem (p) + 4 * SIZE_SZ <= paligned_mem);
assert ((char *) p + size > paligned_mem);
/* This is the size we could potentially free. */
size -= paligned_mem - (char *) p;
if (size > psm1)
madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);
}
Questo è uno dei totali due utilizzi di madvise
con MADV_DONTNEED
in glibc ora, uno per parte superiore della cumuli (shrink_heap
) ed altra è la marcatura di ogni pezzo (mtrim
): http://code.metager.de/source/search?q=MADV_DONTNEED&path=%2Fgnu%2Fglibc%2Fmalloc%2F&project=gnu
H A D arena.c 643 __madvise ((char *) h + new_size, diff, MADV_DONTNEED);
H A D malloc.c 4535 __madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);
Possiamo testare la malloc_trim
con questo semplice programma C (test_malloc_trim.c
) e strace
/ltrace
:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
int main()
{
int *m1,*m2,*m3,*m4;
printf("%s\n","Test started");
m1=(int*)malloc(20000);
m2=(int*)malloc(40000);
m3=(int*)malloc(80000);
m4=(int*)malloc(10000);
// check that all arrays are allocated on the heap and not with mmap
printf("1:%p 2:%p 3:%p 4:%p\n", m1, m2, m3, m4);
// free 40000 bytes in the middle
free(m2);
// call trim (same result with 2000 or 2000000 argument)
malloc_trim(0);
// call some syscall to find this point in the strace output
sleep(1);
free(m1);
free(m3);
free(m4);
// malloc_stats(); malloc_info(0, stdout);
return 0;
}
gcc test_malloc_trim.c -o test_malloc_trim
, strace ./test_malloc_trim
write(1, "Test started\n", 13Test started
) = 13
brk(0) = 0xcca000
brk(0xcef000) = 0xcef000
write(1, "1:0xcca010 2:0xccee40 3:0xcd8a90"..., 441:0xcca010 2:0xccee40 3:0xcd8a90 4:0xcec320
) = 44
madvise(0xccf000, 36864, MADV_DONTNEED) = 0
...
nanosleep({1, 0}, 0x7ffffafbfff0) = 0
brk(0xceb000) = 0xceb000
Quindi, ci fu madvise
con MADV_DONTNEED
per 9 pagine dopo malloc_trim(0)
chiamata, quando c'era un buco di 40008 byte nel mezzo dell'heap.
C'è ora il metodo per restituire i fori nel mezzo dell'heap al sistema operativo: MADV_DONTNEED (e talvolta MADV_FREE): http://code.metager.de/source/xref/gnu/glibc/malloc/malloc.C# 4535 'mtrim (mstate av, size_t pad) ... __madvise (paligned_mem, size & ~ psm1, MADV_DONTNEED);'. 'madvise' con tali flag segna le pagine non necessarie per l'applicazione, il sistema operativo può distruggere i dati da loro e rimuovere lo spazio fisico; il prossimo accesso alla pagina potrebbe generare pagefault per rimappare la pagina virtuale nello spazio fisico. – osgx
Il codice è stato aggiunto in https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc 68631c8eb92ff38d9da1ae34f6aa048539b199cc "(mTRIm): Ulteriore iterazione su tutti i blocchi liberi e usa madvise per liberare memoria per tutti quei blocchi che contengono almeno una pagina di memoria. " - \t Ulrich Drepper 16 dic 2007 (glibc 2.9) – osgx