Schrumpft Hash beim Löschen von Elementen in Perl?
Genauer gesagt hatte ich ein Perl-Programm, das ich geerbt hatte, das eine riesige Datei (1 GB) analysieren und einen Hash von Hashes laden würde. Für eine andere Datei würde es dasselbe tun und dann einen Vergleich verschiedener Elemente vornehmen. Der Speicherverbrauch war während dieses Prozesses enorm und obwohl ich Lösch-Hash-Elemente hinzugefügt habe, wenn sie verwendet wurden, schien der Speicherverbrauch davon nicht betroffen zu sein.
Das Skript war extrem langsam und so ein Speicherfresser. Ich weiß, es war nicht gut entworfen, aber irgendwelche Ideen über die Hash-Speicher-Nutzung?
Im Allgemeinen kann Perl keinen Speicher an das Betriebssystem zurückgeben. Es kann jedoch intern Speicher wiederverwenden, was den von einem Programm benötigten Speicher reduzieren könnte.
Siehe perlfaq3: Wie kann ich ein Array oder Hash freigeben, damit mein Programm schrumpft?
Wenn der von den Hashes verwendete Speicher zu groß ist (d. h. & gt; physischer Speicher), könnten Sie tie
sie zu einer Datei auf der Platte machen. Dies würde die Speicherauslastung stark reduzieren, aber darauf hingewiesen, dass der Zugriff auf eine Struktur auf der Festplatte viel langsamer ist als der Zugriff auf eine im Speicher. (So ist Festplatten-Thrashing.)
Vielleicht möchtest du etwas wie DBM :: Deep ausprobieren. Es tut genau das, was Michael erwähnt hat, damit du nicht darüber nachdenken musst. Alles ist auf der Festplatte gespeichert und nicht im Speicher. Es braucht nur einen schickeren Datenbankserver.
Wenn Sie den Leistungsengpass aufspüren möchten, sollten Sie auch Devel :: NYTProf , das neue, ausprobieren Hotness in Perl Profiling, die aus der New York Times herauskam.
Wenn Ihr Hash-Wert wirklich gigantisch ist, ist es wahrscheinlich eine bessere Strategie, einen Festplatten-Hash zu verwenden und das Betriebssystem sich darum kümmern zu müssen, Dinge in und aus dem Speicher zu bekommen. Ich mag besonders Berkeley DB zum Speichern großer Hashes auf der Festplatte und das Perl BerkeleyDB Modul bietet eine voll funktionsfähige Schnittstelle, einschließlich einer gebundenen API.
DBM :: Deep kann auch als verwendet werden Drop-In-Hash-Ersatz, aber beruht auf seinem eigenen Format. Dies kann ein Schmerz sein, wenn Ihre Struktur von anderen (Nicht-Perl-) Systemen gelesen werden muss.
Bei der spezifischen Frage: Nein, das Löschen von Hash-Schlüsseln reduziert nicht den Speicherverbrauch Ihres Programms.
Was den allgemeineren Fall anbelangt: Die überwiegende Mehrheit der Programme und Sprachen wird weiterhin den Speicher behalten, den sie vorher benutzt haben, aber nicht benutzen. Dies liegt daran, dass die Anforderung der Speicherzuweisung durch das Betriebssystem eine relativ langsame Operation ist, so dass sie beibehalten wird, falls sie später erneut benötigt wird.
Wenn Sie also diese Situation verbessern wollen, müssen Sie den von Ihrem Programm benötigten maximalen Speicherbedarf reduzieren, indem Sie Ihre Algorithmen so anpassen, dass Sie nicht mehr auf so viele Daten gleichzeitig zugreifen müssen. Plattenspeicher (wie der zuvor erwähnte DBM :: Deep) oder durch Freigeben von Speicherplatz von nicht benötigten Variablen zurück in Perl (lassen Sie sie den Gültigkeitsbereich verlassen oder setzen Sie sie auf undef ), damit sie wiederverwendet werden kann.
Wenn Eingaben in der zweiten Datei nur einmal benötigt werden (wie sie gelesen werden), könnte die Speicherbelegung möglicherweise halbiert werden.
Abhängig von Ihrem Algorithmus können Sie möglicherweise sogar beide Dateihandles offen halten und einen kleinen Hashwert für noch nicht verwendete Werte im Speicher haben. Ein Beispiel wäre eine Zusammenführung oder ein Vergleich von sortierten Daten - Sie müssen nur die aktuelle Zeile aus jeder Datei behalten und vergleichen, während Sie weitermachen, und weiterspringen, bis sich die cmp
ändert.
Ein anderer Ansatz könnte sein, mehrere Durchgänge zu machen, besonders wenn Sie einen oder mehrere im Leerlauf befindliche Kerne in Ihrem Rechner haben. Öffnen Sie Read Pipes und lassen Sie Subprozesse die Daten in überschaubaren, vororganisierten Chunks füttern.
Bei allgemeineren Algorithmen können Sie nur vermeiden, für die Speichergröße zu bezahlen, indem Sie sie gegen die Kosten der Festplattengeschwindigkeit tauschen.
In den meisten Fällen gewinnt das Laden jeder Datenquelle in den Speicher nur zur Entwicklungszeit - dann zahlen Sie dafür in Footprint und / oder Geschwindigkeit, wenn N groß wird.
Workaround: Unterteilen Sie einen untergeordneten Prozess, der all diesen Speicher zuweist. Lass es einige zusammengefasste Informationen zurückgeben, wenn es fertig ist. Wenn der gegabelte Prozess stirbt, wird sein Speicher damit einhergehen. Ein bisschen Schmerz, aber funktioniert in einigen Fällen. Ein Beispiel für einen Fall, in dem dies hilfreich wäre, wäre, wenn Sie viele Dateien verarbeiten, jede Datei einzeln, nur einige der Dateien sind groß und es muss ein kleiner Zwischenstatus beibehalten werden.
Tags und Links perl performance