Não tema o ceifador



D, como muitos idiomas atualmente em uso, vem com um Garbage Collector (GC). Muitos tipos de software podem ser desenvolvidos sem pensar no GC, aproveitando ao máximo suas vantagens. No entanto, o GC tem suas falhas e a coleta de lixo não é desejável em alguns cenários. Nesses casos, o idioma permite desativar temporariamente o coletor de lixo ou até mesmo ficar sem ele.



Para tirar o máximo proveito do coletor de lixo e minimizar suas desvantagens, é necessário entender como o GC funciona na linguagem D. Um bom ponto de partida é a página Coleta de Lixo no dlang.org , que traz a justificativa para o GC na linguagem D e fornece algumas dicas sobre como trabalhar com ele. Este é o primeiro de uma série de artigos a abordar o tópico com mais detalhes.



Desta vez, abordaremos apenas o básico, concentrando-nos nas funções de linguagem que podem causar alocação de memória através do GC. Artigos futuros apresentarão maneiras de desativar o GC quando necessário, bem como expressões idiomáticas para ajudar a lidar com seu não determinismo (por exemplo, gerenciamento de recursos em destruidores de objetos sob controle do GC).



A primeira coisa a entender é que o coletor de lixo de D é acionado apenas durante a alocação de memória e somente se não houver memória para alocar. Ele não se senta no fundo, examinando periodicamente a pilha e coletando lixo. Isso deve ser entendido para escrever um código que use efetivamente a memória sob o controle do GC. Considere o seguinte exemplo:



void main() {
    int[] ints;
    foreach(i; 0..100) {
        ints ~= i;
    }
}


Este programa cria uma matriz dinâmica de valores de tipo inte, em seguida, usa o operador de junção em D para adicionar números de 0 a 99 a ele foreach. O que não é óbvio para quem não é treinado é que o operador de junção aloca memória para valores agregados por meio do coletor de lixo.



D . , . , , . , , capacity. , , .



void main() {
    import std.stdio : writefln;
    int[] ints;
    size_t before, after;
    foreach(i; 0..100) {
        before = ints.capacity;
        ints ~= i;
        after = ints.capacity;
        if(before != after) {
            writefln("Before: %s After: %s",
                before, after);
        }
    }
}


DMD 2.073.2,  — GC. , GC . . , GC, .



, before after. : 0, 3, 7, 15, 31, 63, 127. ints 100 , 27 , , 255, . , , D, . , GC , (Steve Schveighoffer) .



, , GC . , , «» . GC .



, C C++, , . ,  — , . , GC D , . :



void main() {
    int[] ints = new int[](100);
    foreach(i; 0..100) {
        ints[i] = i;
    }
}


. , — . 100 . new 100, .



: reserve:



void main() {
    int[] ints;
    ints.reserve(100);
    foreach(i; 0..100) {
        ints ~= i;
    }
}


100 , ( length 0), . , 100 , , .



new reserve, , GC.malloc.



import core.memory;
void* intsPtr = GC.malloc(int.sizeof * 100);
auto ints = (cast(int*)intsPtr)[0 .. 100];


.



auto ints = [0, 1, 2];


, enum.



enum intsLiteral = [0, 1, 2];
auto ints1 = intsLiteral;
auto ints2 = intsLiteral;


enum .  — . , . ints1, ints2 , :



auto ints1 = [0, 1, 2];
auto ints2 = [0, 1, 2];


, . , ( D — ) — .



int[3] noAlloc1 = [0, 1, 2];
auto noAlloc2 = "No Allocation!";


:



auto a1 = [0, 1, 2];
auto a2 = [3, 4, 5];
auto a3 = a1 ~ a2;


D , , . : keys values, . , , - ,  — . , GC.



- , , , . , . , . D : byKey, byValue byKeyValue. , . , , . Ranges More Range (Ali Çehreli) Programming in D.



 — ,  — . , Garbage Collection — assert. , assert , AssertError, D, ( , GC).



, Phobos — D. - - Phobos’ GC, , . , Phobos GC. , , , , , . GC (, , ,  — - ).



Agora que descobrimos o básico do trabalho com o GC, no próximo artigo desta série, veremos quais ferramentas no idioma e no compilador nos permitirão desativar o coletor de lixo e garantir que locais críticos do programa não acessem o GC.



Agradecemos a Guillaume Piolat e Steve Schweihoffer por sua ajuda na preparação deste artigo.




All Articles