glibc malloc () usa mmap () para pequenos blocos de alocação de memória?

1

Eu aprendi que no Linux o malloc () do glibc usa o mmap () para uma grande quantidade de memórias e o brk () é usado para pequenas alocações. No entanto, esse não parece ser o caso quando experimento a teoria com um programa de teste.

Primeiro, eu uso um loop "for" no meu código para atribuir um grande bloco de memória (80MB) implementado por um array com a condição Option1 == TRUE, e cada alocação é um múltiplo do tamanho de uma página. O pedaço de memória será liberado completamente quando Option2 == TRUE. Nota: Opção1 e Opção2 podem ser definidas a partir da linha de comando onde meu processo está sendo executado.

Observação: quando a Opção1 foi satisfeita, o valor de RSS do meu processo aumentou 80MB. Depois disso, defini Option2 como TRUE (enquanto Option1 está insatisfeito), aproximadamente a mesma quantidade de memória foi reduzida do valor de RSS (retornado ao OS). Tudo está bem até agora.

Depois disso, eu modifiquei o loop 'for' para atribuir dois grandes pedaços de memória (80MB cada) implementados pelo chunk e chunk1 com Option1. Dentro de cada loop, os mesmos índices das duas matrizes são atribuídos com a mesma quantidade de memória, e cada alocação é menor do que uma página. O pedaço de memória para o chunk será liberado completamente quando Option2 == TRUE. E o pedaço de memória para chunk1 será liberado completamente quando Option3 == TRUE.

Observação: o valor de RSS do meu processo aumentou 160MB com a Opção1 == TRUE, e o valor permaneceu após a Opção2 == VERDADEIRO. E também permaneceu após Option3 == TRUE. Eu uso a ferramenta Valgrind Massif para verificar o uso de memória e ele relatou que há cerca de 160 MB de páginas mapeadas pelas duas funções malloc () no loop "for".

Eu posso entender que os blocos de memória por pequenas alocações são mantidos no processo para que eles possam ser usados para futuras alocações. Mas essas pequenas alocações não devem ser implementadas pelo brk (), mas não pelo mmap ()? É porque valgrind não fornece o relatório preciso ou porque há alguns outros casos que usam mmap () para implementar malloc ()?

Meu código para o segundo teste é copiado abaixo:

        char *chunk[200000];
        char *chunk1[200000];
        int i = 0;
        int j,k;
......
        if (<Option1 == TRUE>) {
            if (i < 100) {
                for (k=0; k<2000; k++) {
                chunk[i*2000+k] = (char *)malloc(400);
                chunk1[i*2000+k] = (char *)malloc(400);
                memset (chunk[i*2000+k], 0, 400);
                memset (chunk1[i*2000+k], 0, 400);
                }
            }
        }
        if (<Option2 == TRUE>) {
            for (j = 0; j < 200000; j++) {
                if (chunk[j] != NULL) {
                    free(chunk[j]);
                    chunk[j] = NULL;
                }
            }
        }
        if (<Option3 == TRUE>) {
            for (j = 0; j < 200000; j++) {
                if (chunk1[j] != NULL) {
                    free(chunk1[j]);
                    chunk1[j] = NULL;
                }
            }
        }
......
    
por michelle 05.11.2012 / 17:07

1 resposta

2

Isso realmente depende da implementação de malloc . Ele pode pré-alocar um bloco contínuo de memória maior e, em seguida, fazer alguma mágica em cima dele - por exemplo, aloque blocos menores de memória de diferentes partes do bloco grande, dependendo dos tamanhos solicitados. Um bloco tão grande pode, obviamente, ser alocado através de mmap .

Você pode verificar, por exemplo, a fonte do jemalloc para ter uma ideia de como isso funciona.

    
por 06.11.2012 / 00:29

Tags