¿Qué tan diferente es la recolección de basura en idiomas puros?

26

En un lenguaje puro como Haskell, todos los datos son inmutables y ninguna estructura de datos existente se puede cambiar de ninguna manera. Además, muchos algoritmos sobre datos inmutables y patrones de programación funcional generan grandes cantidades de basura por naturaleza (cadenas de mapcreación de listas intermedias, por ejemplo).

¿Qué estrategias y técnicas emplean los recolectores de basura frente a la pureza que de otro modo no harían? ¿Qué funciona muy bien en un GC de lenguaje impuro que no lo hace en un contexto puro? ¿Qué otros problemas nuevos crean los lenguajes puros para los GC?

Jack
fuente
1
es posible que desee leer este wiki.haskell.org/GHC/Memory_Management
Mateusz K.

Respuestas:

13

La implementación actual de ghc utiliza una estrategia que solo funciona porque el lenguaje es puramente funcional y los datos son inmutables: dado que ninguna variable puede ser alterada para referirse a algo más nuevo, los objetos solo contienen referencias a objetos más antiguos, por lo que ejecuta un recolector de basura generacional ; dado que un objeto al que hace referencia una generación superior no se puede eliminar hasta que esa generación sea GCd, promueve los objetos entre generaciones superiores con entusiasmo; y como nada alterará las referencias mientras el GC las barre, puede ejecutarse en paralelo.

Aquí hay un artículo con más detalles .

Davislor
fuente
44
La promoción entusiasta se basa en la pereza: la actualización de un thunk en una generación anterior puede crear un puntero en la nueva generación, pero los thunks solo mutan una vez, por lo que es suficiente para promover con entusiasmo el objeto joven. Otras referencias de viejos a jóvenes (por ejemplo, de matrices mutables) se rastrean usando "conjuntos recordados", que también se usan en caso de que falle la promoción entusiasta.
Jon Purdy
1

En un lenguaje puro como Haskell, todos los datos son inmutables y ninguna estructura de datos existente se puede cambiar de ninguna manera.

En realidad, eso no es generalmente cierto. Los lenguajes puros utilizan una evaluación no estricta (perezosa), por lo que se aplaza la evaluación de potencialmente todas las subexpresiones. Las expresiones no evaluadas generalmente se asignan en montón como un "thunk". Cuando se requiere, se evalúa la expresión y se muta el thunk en el valor resultante.

¿Qué estrategias y técnicas emplean los recolectores de basura frente a la pureza que de otro modo no harían?

Lo único en lo que puedo pensar es en los agujeros negros . No recuerdo haber visto nada más nuevo en el lado de GC en los documentos de investigación de Haskell.

¿Qué funciona muy bien en un GC de lenguaje impuro que no lo hace en un contexto puro?

La barrera de escritura GC. Los idiomas impuros tienden a escribir punteros en el montón mucho más, por lo que tienden a tener sus barreras de escritura más optimizadas.

Otros algoritmos de GC como mark-region son mucho más viables en el contexto de lenguajes impuros porque pueden tener tasas de asignación mucho más bajas que los lenguajes puros.

¿Qué otros problemas nuevos crean los lenguajes puros para los GC?

Los lenguajes puros son muy raros, por lo que hay muchos menos datos sobre cómo los programas puros usan la memoria y, por lo tanto, está empezando en una posición peor cuando intenta escribir un GC para un lenguaje puro.

Jon Harrop
fuente
"Cuando se requiere, se evalúa la expresión y se muta el thunk en el valor resultante". Eso es un detalle de implementación interna en lo que respecta a un usuario de Haskell. No hay forma de observar la mutación, por lo que no es una mutación desde el punto de vista del usuario.
Jack
Además, es completamente posible que un lenguaje puro sea estricto; vea Idris para ver un ejemplo.
Jack