perl garbage-collection circular-reference

Recolección de basura en Perl



garbage-collection circular-reference (4)

A diferencia de Java, Perl usa el recuento de referencias para la recolección de basura. He intentado buscar algunas preguntas anteriores que hablan sobre C ++ RAII y punteros inteligentes y Java GC, pero no he entendido cómo Perl trata el problema de las referencias circulares.

¿Alguien puede explicar cómo el recolector de basura de Perl trata con referencias circulares? ¿Hay alguna manera de reclamar memoria de referencia circular que el programa ya no usa o Perl simplemente ignora este problema por completo?



Perl aplica un GC alterno de marcaje y barrido en algunas ocasiones (cuando un hilo muere, creo) para reclamar referencias circulares. Tenga en cuenta que "cada valor es una cadena" La estrofa de Perl dificulta la creación de referencias circulares verdaderas; esto es factible, pero el código Perl "normal" no, por lo que el recuento de referencias funciona bien con Perl.


De acuerdo con mi copia de Programming Perl 3rd ed. , en la salida, Perl 5 realiza una "marca y un barrido costosos" para reclamar referencias circulares. Deberá evitar las referencias circulares tanto como sea posible porque, de lo contrario, no se recuperarán hasta que el programa finalice.

Perl 5 ofrece referencias débiles a través del módulo Scalar :: Utils .

Perl 6 pasará a un esquema de recolección de basura conectable (bueno, la VM subyacente tendrá múltiples opciones de recolección de basura y el comportamiento de esas opciones puede tener un efecto en Perl). Es decir, podrá elegir entre varios recolectores de basura o implementar los suyos propios. ¿Quieres un coleccionista de copias? Por supuesto. ¿Quieres un coleccionista de colorante? Lo tienes. Marcar / barrer, compactar, etc. Por qué no?


La respuesta rápida es que Perl 5 no maneja referencias circulares automáticamente. A menos que tome medidas explícitas en su código, cualquiera de sus estructuras de datos que incluyan referencias circulares no será reclamada hasta que muera el hilo que las creó. Esto se considera una compensación aceptable ya que evita la necesidad de recolección de basura en tiempo de ejecución que ralentizaría la ejecución.

Si su código crea estructuras de datos con referencias circulares (es decir, un árbol cuyos nodos contienen referencias de la raíz), querrá usar el módulo Scalar :: Util para "debilitar" las referencias que apuntan hacia el nodo raíz. Estas referencias débiles no se agregarán al recuento de referencias de lo que sea que señalen, por lo que toda la estructura de datos se desasignará automáticamente cuando desaparezca la última referencia externa.

Ejemplo:

use Scalar::Util qw(weaken); ... my $new_node = { content => $content, root => $root_node }; weaken $new_node->{root}; push @{$root_node->{children}}, $new_node;

Si usa un código como este cada vez que agrega nuevos nodos a su estructura de datos, entonces las únicas referencias a la raíz que realmente se cuentan son aquellas desde fuera de la estructura. Esto es exactamente lo que quieres. A continuación, la raíz y recursivamente todos sus elementos secundarios se recuperarán en cuanto desaparezca la última referencia externa.