Perl: Wie kann man Speicher freigeben, der für einen Skalar ohne Zugriff auf die Perl-Variable reserviert ist?

8

Diese Frage bezieht sich auf eine Antwort auf eine frühere Frage über die Speicherbehandlung von Perl. Ich habe gelernt, dass man Speicher in Perl freigeben kann, indem man explizit die Funktion undef auf einem verfügbaren Skalar verwendet und Devel::Peek oder Devel::Size verwendet oder man kann sehen, wie viel Speicher für einen Skalar reserviert ist. In all diesen Fällen werden die Debugger innerhalb ihres Gültigkeitsbereichs verwendet.

Aber ist es möglich, Dinge wie reservierten Speicher außerhalb des Bereichs von Variablen zu debuggen, nur auf der Ebene eines Perl-Interpreters? So etwas wie die Suche nach dem gesamten zugewiesenen Speicher für alle "Dinge", die im aktuellen Interpreter ein Skalar sind und deren zugehörige Daten, wie den aktuellen Wert oder dergleichen, ausgeben?

Und wenn das der Fall ist, wenn man diese Information schon hat, kann man das bekannte Gedächtnis sogar befreien? Genauso wie man undef auf einem Skalar aufruft, aber ohne den Skalar, etwas niedrigeres Niveau, wie bei diesen "Dingen", die von Devel::Peek ausgegeben werden.

Was ich darüber denke ist, dass nach einer Anfrage ein mod_perl-Bereinigungs-Handler ausgeführt wird, der den aktuellen mod_perl-Interpreter nach großen Datenmengen durchsucht und sie manuell freigibt. Ganz einfach, weil ich beschließe, dass große Blöcke zugeordneter Daten nichts mehr nützen, auch wenn Perl anders denkt:

  

Schließlich und vielleicht der größte Gewinn ist die Wiederverwendung von Speicher: Wenn Aufrufe in Perl-Subroutinen gemacht werden, werden Speicherzuweisungen für Variablen vorgenommen, wenn sie zum ersten Mal verwendet werden. Die nachfolgende Verwendung von Variablen kann mehr Speicher zuweisen, z. Wenn eine Skalarvariable eine längere Zeichenfolge als zuvor speichern muss oder ein Array neue Elemente hinzugefügt hat. Als Optimierung hängt Perl an diesen Zuordnungen, obwohl ihre Werte "außerhalb des Gültigkeitsbereichs" liegen.

Ссылка

Ich konnte eine Menge von Überwachungs- und Debugging-Paketen um Low-Level-Speicherzugriff finden, aber noch keinen Hinweis, wie man etwas wie die undef -Funktion auf einer Perl-Struktur auf niedriger Ebene in Perl nennen könnte. Könnte einfach nicht ohne XS oder so möglich sein ...

    
Thorsten Schöning 16.09.2016, 08:47
quelle

3 Antworten

3
  

ist es möglich, Dinge wie zugewiesenen Speicher außerhalb des Gültigkeitsbereichs von Variablen zu debuggen

Es gibt wirklich keine solche Erinnerung. Irgendein Speicher, der außerhalb von Variablen zugewiesen ist, wird sicherlich benötigt. Wie Sie selbst betonen, ist es der Speicherplatz, der für Variablen reserviert ist, die den meisten "verschwendeten" Platz ausmachen.

  

aber noch kein Hinweis, wie man etwas wie die undef-Funktion auf einer Perl-Struktur in Perl auf niedriger Ebene nennen könnte.

Das liegt daran, dass es keine solchen Strukturen gibt.

  

Genauso wie% ce_de% auf einem Skalar aufgerufen wird, aber ohne den Skalar, etwas niedrigeres Niveau, wie bei diesen "Dingen", die von Devel :: Peek ausgegeben werden.

Devel_Peeks einzige Funktion, undef , gibt Dinge in Variablen aus. Wie Sie gesagt haben,% c: o% ist das, was Sie löschen möchten.

Aus den obigen Ausführungen geht klar hervor, dass Sie wissen möchten, wie Sie den Speicher freigeben können, der mit den Variablen in Subs verknüpft ist.

Sie haben auch übersehen, dass viele Operatoren eine assoziierte Variable haben ("target" genannt), in der sie ihr Ergebnis zurückgeben.

Ansatz 1

Eine einfache Möglichkeit zum Löschen all dieser Variablen wäre das selektive Löschen der Symboltabelle ( Dump ). Dies würde effektiv jedes Modul "entladen". Stellen Sie sicher, dass Sie die Kernkomponenten nicht löschen ( undef ). Und vergessen Sie nicht, %:: zu löschen, damit die Module neu geladen werden können.

Wenn Sie die Symboltabelle löschen möchten, ist es möglicherweise weniger riskant und zeitaufwendig, zu einem frühen Zeitpunkt einen Snapshot von perl -E'say for sort keys %::' zu erstellen und diesen Snapshot wiederherzustellen, wenn es Zeit ist, das Symbol zu löschen.

Ansatz 2

Wenn Sie die Module nicht neu laden wollten, könnten Sie versuchen, jedes Sub zu lokalisieren und deren Variablen zu dekodieren, und dann die Variablen ihrer Ops zu deaktivieren.

Die Vars eines Subs existieren innerhalb seiner Pads . Praktischerweise tun dies auch Opcode-Ziele. Es gibt ein Pad für jede Rekursionsstufe, die das Sub erfahren hat.

Wenn Sie einen Verweis auf ein Sub-Objekt angeben, können Sie die Variablen in den Pads eines Sub-Objekts finden. Ein Beispiel dafür finden Sie in PadWalker . Sie können PadWalker nicht wirklich verwenden, da er nur eine Variable pro Variablennamen zurückgibt, auch wenn es mehrere gibt (weil mehr als eine Variable mit demselben Namen oder aufgrund einer Rekursion deklariert wurde).

Captured Variablen und %INC Variablen sollten nicht verändert werden. Es ist möglich zu erkennen, ob ein Pad-Eintrag einer davon ist. (Siehe auch PadWalker.)

(Natürlich könntest du auch die zusätzlichen Pads des Subs befreien!)

Wie findest du alle U-Boote? Nun, das Navigieren durch die Symboltabelle wird Ihnen die meisten geben. Anon zu finden, wird schwieriger.

Ansatz 3

Am effizientesten ist es, den mod_perl-Thread / -Prozess einfach zu beenden. Ein neues sauberes wird automatisch erzeugt. Es ist auch am einfachsten zu implementieren, da es einfach eine Konfigurationsänderung ist (Einstellung %:: auf our ).

Eine andere Form von verschwendeten Speicher ist ein Speicherleck. Das ist eine andere große Frage, also berühre ich sie nicht.

    
ikegami 16.03.2017, 20:49
quelle
1

Ich glaube, Sie suchen diese Antwort nach einer ähnlichen Frage. Alles, was Sie wirklich wissen müssen, finden Sie in den Interna zu den Devel :: MAT :: * Submodulen. Nämlich die Devel :: MAT :: Dumper.xs , welches die Struktur des Heaps für Perl-Interpreter hat. Das Modul ist dafür ausgelegt, den Heap bei Signal zu speichern und später zu analysieren, aber ich denke, Sie können es in eine Laufzeitprüfung umwandeln. Wenn Sie Hilfe beim Lesen der XS benötigen, schauen Sie hier nach.

    
Jiri Klouda 23.02.2017 02:35
quelle
-1

Um die Speicherzuweisung zu debuggen, sollten Sie Perl mit -Accflags=-DPERL_MEM_LOG DOC

neu kompilieren

(siehe verwandte Frage zu wie man Perl neu kompiliert ) )

Sie werden sich vielleicht für MEMORY DEBUGGERS

interessieren

Um Perl-Skalar freizugeben, genau wie wenn sie ihren Bereich verlässt:

%Vor%

Sie sollten nur die Variable REFCNT auf Null reduzieren, indem Sie SvREFCNT_dec macro DOC eingeben

  

Um einen von Ihnen erstellten SV freizugeben, rufen Sie SvREFCNT_dec (SV *) auf. Normalerweise ist dieser Aufruf nicht notwendig (siehe Referenzzählungen und Mortalität).

Hier ist Pseudocode:

%Vor%

XS Pseudocode:

%Vor%

Um jede Speicherzuordnung zu sehen, sollten Sie in Perl-Arenen gehen.

Zur Kompilierzeit können Sie jeden Ort anzeigen, an dem die Variable deklariert und mit Hilfe des Moduls B :: Xref aufgerufen wird

Oder Perl mit -Dm -Option ausführen (Das Perl sollte mit entsprechenden Optionen kompiliert werden. Siehe hierzu topic ):

%Vor%     
Eugen Konkov 16.03.2017 11:37
quelle