Perl utiliza un algoritmo de conteo de referencias para la gestión automática de la memoria: cada variable tiene un contador de referencias. Cuando el contador llega a cero, se libera la memoria. En la mayoría de los casos, esto funciona de forma transparente: las variables no utilizadas se eliminan tan pronto como salen del ámbito.
El problema surge con las referencias circulares (por ejemplo, un objeto se refiere a sí mismo o dos estructuras se refieren entre sí). En este caso, el contador de referencias nunca llegará a cero y la memoria no se liberará.
Para evitar pérdidas de memoria, se utiliza el módulo Scalar::Util::weaken, que permite crear referencias "débiles" que no incrementan el contador de referencias.
Ejemplo:
use Scalar::Util qw(weaken); my $a = {}; my $b = { ref => $a }; $a->{ref} = $b; weaken($a->{ref}); # ahora no hay dependencia fuerte cíclica
¿Es correcto suponer que Perl siempre libera automáticamente toda la memoria no utilizada, incluso en estructuras interrelacionadas complejas?
Respuesta y ejemplo:
¡No! En el caso de referencias circulares, Perl no podrá liberar la memoria automáticamente a menos que se use weaken:
my $a = {}; $a->{self} = $a; # ciclo # $a nunca se eliminará automáticamente; se requerirá una ruptura manual o debilitar la referencia
Historia 1: En un gran servicio web en Perl había una fuga de memoria: las sesiones de los usuarios mantenían referencias entre sí en un hash, y nadie utilizaba referencias débiles. El servicio agotaba todos los recursos en un día, se colgaba y requería reinicios.
Historia 2: Un ORM hecho a mano creaba ciclos entre objetos User y Group, cada uno de los cuales se refería al otro. Después de salir del ámbito, los objetos permanecían en memoria, ¡y el servicio gradualmente "se inflaba" hasta decenas de gigabytes!
Historia 3: El uso de subprogramas anónimos ("cierres") como métodos de clase, que se refieren a
$self, causaba pérdidas de memoria en cada creación de objeto hasta que apareció un analizador que identificó las referencias circulares y señaló la necesidad deweaken.