In Perl wordt het geheugen voor variabelen en datastructuren beheerd met behulp van een referentietellingmechanisme (reference counting). Een object of structuur wordt vrijgegeven wanneer de referentieteller op nul komt.
Echter, dit mechanisme behandelt geen cyclische referenties. Als objecten naar elkaar verwijzen, bereiken hun tellers nooit nul, en het geheugen wordt niet vrijgegeven.
Voor het opruimen van cyclische referenties worden de volgende methoden gebruikt:
Scalar::Util::weaken. Een zwakke referentie verhoogt de referentieteller niet, waardoor GC het object kan vrijgeven als er geen andere sterke referenties zijn.Voorbeeld van het maken van een zwakke referentie:
use Scalar::Util 'weaken'; my $parent = {}; my $child = { parent => $parent }; $parent->{child} = $child; weaken($child->{parent}); # nu hinder parent->child->parent geen opruiming
Kan Perl zelf "detecteren" en cyclische referenties vrijgeven zonder de Scalar::Util-module of handmatige interventie?
Nee, Perl kan standaard geen cyclische structuren automatisch "opruimen", omdat dit mechanisme een analyse van de objectgrafenstructuur vereist (zoals bij de GC in JVM of Python). Dus je moet altijd zelf zorgen voor het opruimen van cycli.
Verhaal
In een sessieopslagserver voor een webapplicatie werden User-objecten met bidirectionele referenties actief gebruikt. Het bleek dat na enkele duizenden aanvragen het geheugen van het proces groeide door cycli: $user->{session}->{user} = $user. De lek verdween na de invoering van weaken voor omgekeerde referenties.
Verhaal
Bij het gebruik van een cache met een LRU-algoritme werden objectketens aan elkaar gekoppeld via referenties. De ontwikkelaars hadden geen handmatige nulzetting van de verbindingen voorzien, wat leidde tot een snelle stijging van het geheugen na enkele dagen werking van de dienst en een crash door OOM.
Verhaal
In een complexe microservice voor documentopslag werden bij het genereren van rapporten eval en grootschalige datastructuren met cyclische referenties gebruikt. De ontwikkelaars rekenden op de automatische garbage collection van Perl, maar de server "onthield" oude objecten en na een week arbeid had het al het beschikbare RAM verloren. Diagnostiek onthulde de cycli en gebruikte Scalar::Util na elk rapport.