Quão diferente é a coleta de lixo em idiomas puros?

26

Em uma linguagem pura como Haskell, todos os dados são imutáveis ​​e nenhuma estrutura de dados existente pode ser alterada de forma alguma. Além disso, muitos algoritmos em dados imutáveis ​​e padrões de programação funcional geram grandes quantidades de lixo por natureza (cadeias de mapcriação de listas intermediárias, por exemplo).

Quais estratégias e técnicas os coletores de lixo empregam em face da pureza que eles não usariam de outra maneira? O que funciona muito bem no GC de uma linguagem impura que não funciona em um contexto puro? Que outros novos problemas os idiomas puros criam para os GCs?

Jack
fonte
1
você pode querer ler este wiki.haskell.org/GHC/Memory_Management
Mateusz K.

Respostas:

13

A implementação atual do ghc usa uma estratégia que funciona apenas porque a linguagem é totalmente funcional e os dados são imutáveis: como nenhuma variável pode ser alterada para se referir a algo mais novo, os objetos mantêm apenas referências a objetos mais antigos, portanto, executam um coletor de lixo geracional ; como um objeto referido por uma geração superior não pode ser excluído até que a geração seja GCd, ele promove objetos para as gerações superiores ansiosamente; e como nada altera as referências enquanto o GC as varre, ele pode ser executado em paralelo.

Aqui está um artigo com mais detalhes .

Davislor
fonte
4
A promoção ansiosa depende da preguiça - a atualização de um thunk em uma geração antiga pode criar um ponteiro para a nova geração, mas os thunks só são modificados uma vez, portanto basta promover o objeto jovem com entusiasmo. Outras referências de velhos para jovens (por exemplo, de matrizes mutáveis) são rastreadas usando "conjuntos lembrados", que também são usados ​​no caso de uma promoção ansiosa falhar.
Jon Purdy
1

Em uma linguagem pura como Haskell, todos os dados são imutáveis ​​e nenhuma estrutura de dados existente pode ser alterada de forma alguma

Na verdade, isso geralmente não é verdade. Linguagens puras usam avaliação não estrita (preguiçosa) para que a avaliação de potencialmente todas as subexpressões seja adiada. Expressões não avaliadas geralmente são alocadas em heap como um "thunk". Quando necessário, a expressão é avaliada e a conversão é alterada para o valor resultante.

Quais estratégias e técnicas os coletores de lixo empregam em face da pureza que eles não usariam de outra maneira?

A única coisa em que consigo pensar é nos buracos negros . Não me lembro de ter visto mais nada do lado do GC nos trabalhos de pesquisa de Haskell.

O que funciona muito bem no GC de uma linguagem impura que não funciona em um contexto puro?

A barreira de gravação do GC. Linguagens impuras tendem a escrever ponteiros muito mais no heap, e tendem a ter suas barreiras de gravação mais fortemente otimizadas.

Outros algoritmos de GC, como região de marca, são muito mais viáveis ​​no contexto de linguagens impuras porque podem ter taxas de alocação muito mais baixas do que linguagens puras.

Que outros novos problemas os idiomas puros criam para os GCs?

Linguagens puras são muito raras; portanto, há muito menos dados sobre como os programas puros usam a memória e, portanto, você está começando em uma posição pior ao tentar escrever um GC para uma linguagem pura.

Jon Harrop
fonte
"Quando necessário, a expressão é avaliada e a conversão é alterada para o valor resultante." Esse é um detalhe interno da implementação no que diz respeito a um usuário Haskell. Não há como observar a mutação, portanto não é uma mutação do ponto de vista do usuário.
Jack
Além disso, é perfeitamente possível que uma linguagem pura seja rigorosa - veja Idris como exemplo.
Jack