2013-03-20 9 views
5

Il manual page mi ha detto così tanto e attraverso di esso conosco molte delle conoscenze di base sulla gestione della memoria di "glibc".cosa significa "malloc_trim (0)" veramente?

Ma mi confondo ancora. "malloc_trim (0)" (nota zero come parametro) significa (1.) tutta la memoria nella sezione "heap" verrà restituita al sistema operativo? Oppure (2.) tutta la memoria "non utilizzata" della parte più alta dell'heap verrà restituita al sistema operativo?

Se la risposta è (1.), cosa succede se la memoria ancora utilizzata nell'heap? se l'heap ha usato momery in qualche posto, saranno eliminati o la funzione non verrebbe eseguita correttamente?

Mentre se la risposta è (2.), che dire di quei "buchi " in luoghi piuttosto che in alto nel mucchio? Sono più memoria inutilizzata, ma la regione più cima al mucchio è ancora usato, questa chiamata funzionerà in modo efficiente?

Grazie.

risposta

4

La pagina di manuale per malloc_trim dice che rilascia memoria libera, quindi se nell'heap è allocata memoria, non verrà rilasciato l'intero heap. Il parametro è lì se sai che hai ancora bisogno di una certa quantità di memoria, quindi liberare più di quello farebbe in modo che glibc debba fare un lavoro non necessario in seguito.

Come per i fori, questo è un problema standard con la gestione della memoria e la restituzione della memoria al sistema operativo. La gestione heap di basso livello principale disponibile per il programma è brk e sbrk e tutto ciò che possono fare è estendere o ridurre l'area heap modificando la parte superiore. Quindi non c'è modo per loro di restituire buchi al sistema operativo; una volta che il programma ha chiamato sbrk per allocare più heap, tale spazio può essere restituito solo se la parte superiore di quello spazio è libera e può essere restituita.

Si noti che esistono altri modi più complessi per allocare memoria (ad esempio con mmap anonimo), che possono avere diversi vincoli rispetto all'allocazione basata su sbrk.

+0

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

+0

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

0
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_trimmalloc/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_DONTNEEDhttps://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.

+0

Tipica posizione ufficiale del manutentore del progetto simile a GNU sulle pagine man e altra documentazione: https://sourceware.org/bugzilla/show_bug.cgi?id=2531#c4 "Ulrich Drepper 2006-05-01 Le pagine man non vengono mantenute in glibc. Dillo al manutentore della pagina man. " – osgx