2013-03-20 12 views
5

manual page powiedział mi tak dużo, a dzięki temu znam wiele podstawowych informacji na temat zarządzania pamięcią "glibc".Co naprawdę oznacza "malloc_trim (0)"?

Ale nadal się mylę. czy "malloc_trim (0)" (zanotować zero jako parametr) oznacza (1.) cała pamięć w sekcji "sterty" zostanie zwrócona do systemu operacyjnego? Lub (2.) tylko cała "nieużywana" pamięć najwyższego regionu sterty zostanie zwrócona do systemu operacyjnego?

Jeśli odpowiedź brzmi (1.), co jeśli nadal używana pamięć w stercie? czy sterty używają momery w miejscach gdzieś, czy zostaną wyeliminowane, czy funkcja nie zadziała poprawnie?

natomiast jeżeli odpowiedź jest (2.), co o tych „otworów” w miejscach, zamiast góry w kupie? Oni już nieużywaną pamięć, ale top najbardziej rejon hałdy jest nadal używane, czy to wezwanie działa wydajnie?

Dzięki.

Odpowiedz

4

Strona podręcznika dla malloc_trim mówi, że zwalnia wolną pamięć, więc jeśli zostanie przydzielona pamięć w stercie, nie zwolni całej sterty. Parametr jest dostępny, jeśli wiesz, że nadal potrzebujesz pewnej ilości pamięci, więc zwolnienie większej liczby spowoduje, że glibc będzie musiał wykonać niepotrzebną pracę później.

Co do otworów, jest to standardowy problem z zarządzaniem pamięcią i zwracaniem pamięci do systemu operacyjnego. Podstawowym zarządzaniem stertą niskiego poziomu dostępnym dla programu jest brk i sbrk, a wszystko, co mogą zrobić, to rozciągnąć lub zmniejszyć obszar sterty, zmieniając górę. Tak więc nie ma możliwości, aby zwracali dziury w systemie operacyjnym; gdy program zadzwoni pod numer sbrk, aby przydzielić więcej sterty, to miejsce to może zostać zwrócone tylko, jeśli górna część tego obszaru jest wolna i może zostać przekazana z powrotem.

Należy pamiętać, że istnieją inne, bardziej złożone sposoby przydzielania pamięci (na przykład z anonimowym mmap), które mogą mieć różne ograniczenia niż przydział oparty na sbrk.

+0

Istnieje obecnie metoda zwracania dziur w środku sterty z powrotem do systemu operacyjnego: MADV_DONTNEED (i czasami 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' z takimi flagami oznacza strony, które nie są potrzebne dla aplikacji, system operacyjny może niszczyć dane i odwzorowywać fizyczną przestrzeń; następny dostęp do strony może wygenerować pagefault, aby zamienić stronę wirtualną w przestrzeń fizyczną. – osgx

+0

Kod został dodany w https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc 68631c8eb92ff38d9da1ae34f6aa048539b199cc "(mTRIm): dodatkowo iteracyjne nad wszystkimi wolnymi blokami i użyj madvise, aby zwolnić pamięć dla wszystkich bloków, które zawierają przynajmniej jedną stronę pamięci. " - \t Ulrich Drepper 16 grudnia 2007 (glibc 2.9) – osgx

0

Man strona malloc_trim popełniono tutaj: https://github.com/mkerrisk/man-pages/blob/master/man3/malloc_trim.3 i jak rozumiem, że został napisany przez Manuali projektu opiekuna, Kerrisk w 2012 roku od podstaw: https://github.com/mkerrisk/man-pages/commit/a15b0e60b297e29c825b7417582a33e6ca26bf65

Jak mogę grep the glibc's git, there are no man pages in the glibc i nie zobowiązują do malloc_trim manpage do udokumentowania tej poprawki. Najlepsza i jedyna dokumentacja glibc malloc jest jego kod źródłowy: https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c Istnieje malloc_trim komentarze z 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 

uwalniając od połowy fragmentu nie jest udokumentowane jako tekst w malloc/malloc.c i nieudokumentowane w projekcie stron man. Strona man z 2012 roku może być pierwszą stroną man funkcji, napisaną nie przez autorów glibc. Na stronie informacyjnej glibc wspomniano tylko M_TRIM_THRESHOLD o wartości 128 KB: https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html#Malloc-Tunable-Parameters i nie wyświetlają funkcji malloc_trim https://www.gnu.org/software/libc/manual/html_node/Summary-of-Malloc.html#Summary-of-Malloc (a także nie dokumentują memusage/memusagestat/libmemusage.so).

W grudniu 2007 roku został popełniony https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc przez Ulricha Dreppera (jest to część glibc 2.9 i nowsze), która zmieniła mtrim realizacji (ale to nie zmienia żadnej dokumentacji lub strony człowieka, gdyż nie ma strony man w glibc):

  • malloc/malloc.c (public_mTRIm): Iteracja nad wszystkim Arenas i zadzwonić

mTRIm dla nich wszystkich. (mTRIm): Dodatkowo wykonaj iterację wszystkich wolnych bloków i użyj madvise , aby zwolnić pamięć dla wszystkich bloków, które zawierają co najmniej jedną stronę pamięci .

Nieużywane części kawałki (w dowolnym miejscu, łącznie z kawałkami w środku), ustawionych na rozmiar i o wielkość większą niż strona może być oznaczony jako 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); 
     } 

to jest łącznie dwóch zastosowań od madvise z MADV_DONTNEED w glibc Teraz, po jednym dla górnej części (shrink_heap hałdy), a drugi jest oznaczenie dowolnego fragmentu (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); 

Możemy przetestować malloc_trim z tego prostego programu C (test_malloc_trim.c) i 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 

Więc nie było madvise z MADV_DONTNEED do 9 stron po malloc_trim(0) zadzwonić, gdy na środku stosu była dziura 40008 bajtów.

+0

Typowe oficjalne stanowisko opiekuna projektu GNU na stronach man i innych dokumentach: https://sourceware.org/bugzilla/show_bug.cgi?id=2531#c4 "Ulrich Drepper 2006-05-01 Strony podręcznika man nie są przechowywane w glibc. Powiedz to do opiekuna strony podręcznika. " – osgx