2010-06-04 18 views
12

Im Gegensatz zu Java verwendet Perl Referenzzähler für die Garbage Collection. Ich habe versucht, einige vorherige Fragen zu lesen, die über C++ RAII und Smartpointer und Java GC sprechen, aber ich habe nicht verstanden, wie Perl mit dem Zirkelreferenzierungsproblem umgeht.Garbage Collection in Perl

Kann mir jemand erklären, wie sich Perls Müllsammler mit Zirkelverweisen befasst? Gibt es eine Möglichkeit, zirkulär referenzierten Speicher zurückzugewinnen, die vom Programm nicht mehr verwendet werden, oder ignoriert Perl dieses Problem einfach vollständig?

Antwort

13

Laut meiner Kopie von Programmierung Perl 3. ed., beim Verlassen macht Perl 5 eine "teure Markierung und einen Sweep", um zirkuläre Referenzen zurückzugewinnen. Sie sollten zirkuläre Referenzen so weit wie möglich vermeiden, da sie andernfalls erst nach dem Beenden des Programms wiederhergestellt werden.

Perl 5 bietet schwache Referenzen durch das Modul Scalar::Utils.

Perl 6 wird in ein Pluggable Garbage Collection-Schema verschoben (naja, die underlying VM will have multiple garbage collection options und das Verhalten dieser Optionen können sich auf Perl auswirken). Das heißt, Sie können zwischen verschiedenen Garbage Collectors wählen oder Ihre eigenen implementieren. Willst du einen Sammler kopieren? Sicher. Willst du einen Farbsammler? Du hast es. Markieren/fegen, verdichten usw.? Warum nicht?

+4

Nit: Perl 5 verwendet Referenzzählung. Das ist ein Speicherbereinigungsschema. – tsee

+0

OK, ich habe den Verweis auf Perl 6-Speicherbereinigung geändert. –

+1

Danke für die Aktualisierung der Antwort. NB: Steckbare Müllsammler scheinen eine schreckliche Idee zu sein. Eine gute Möglichkeit, Dinge zu verlangsamen und/oder dubiose Aktionen aus der Ferne zu erzeugen, wenn man Müllsammler anpackt, die unterschiedliche Versprechungen bezüglich der GC-Zeit machen. – tsee

-8

Perl verwendet eine Mark-and-Sweep-Alternative GC in einigen Fällen (wenn ein Thread stirbt, denke ich), um Zirkelbezüge zurückzugewinnen. Beachten Sie, dass die Perl-Zeilengruppe "Jeder Wert ist eine Zeichenkette" es schwierig macht, echte Zirkelverweise zu erstellen. das ist machbar, aber "normaler" Perl-Code nicht, weshalb Reference-Counting mit Perl gut funktioniert.

+0

Schnelle Möglichkeit, einen SV-Perl-Aufruf zu verlieren 'sub leak {my $ r; $ r = \ $ r; } ' Während dies ein künstliches Beispiel ist, ist es nicht schwer, das Äquivalent zu tun, ohne es zu bemerken. –

+7

Das ist einfach falsch; Perl glaubt nicht, dass jeder Wert eine Zeichenkette ist. 'my $ hashref = {a => 1};' lässt '$ hashref' als tatsächliche Referenz, nicht als Zeichenfolge. Dies ist seit Perl 5 der Fall, der im Oktober ** vor 17 Jahren veröffentlicht wurde. (Natürlich wird Perl den Verweis auf eine Zeichenfolge konvertieren, aber diese Konvertierung ist in eine Richtung) – derobert

2

Die schnelle Antwort ist, dass Perl 5 nicht behandelt kreisförmige Referenzen automatisch. Sofern Sie keine expliziten Maßnahmen in Ihrem Code treffen, werden alle Ihre Datenstrukturen, die Zirkelbezüge enthalten, nicht zurückgenommen, bis der Thread, der sie erstellt hat, stirbt. Dies wird als ein akzeptabler Kompromiss angesehen, da es die Notwendigkeit einer Laufzeit-Speicherbereinigung vermeidet, die die Ausführung verlangsamen würde.

Wenn Ihr Code Datenstrukturen mit Zirkelverweisen erstellt (dh eine Baumstruktur, deren Knoten Verweise auf den Stamm enthalten), sollten Sie das Scalar :: Util-Modul verwenden, um die Referenzen zum Stamm zu "schwächen" Knoten. Diese schwachen Referenzen werden nicht zum Referenzzähler dessen, worauf sie zeigen, hinzugefügt, so dass die gesamte Datenstruktur automatisch freigegeben wird, wenn die letzte externe Referenz verschwindet.

Beispiel:

use Scalar::Util qw(weaken); 

... 

    my $new_node = { content => $content, root => $root_node }; 
    weaken $new_node->{root}; 
    push @{$root_node->{children}}, $new_node; 

Wenn Sie Code verwenden, wenn Sie neue Knoten zu Ihrer Datenstruktur hinzufügen, dann die einzigen Hinweise auf die Wurzel, die tatsächlich gezählt werden, sind solche von außerhalb der Struktur. Das ist genau was du willst. Dann werden die Wurzel und rekursiv alle ihre untergeordneten Elemente zurückgeholt, sobald die letzte externe Referenz darauf verschwindet.