2008-09-24 6 views
8

Schrumpft ein Hash in Perl, wenn Sie Elemente löschen.Verkleinert sich ein Hash in Perl, wenn Sie Elemente löschen?

Genauer gesagt hatte ich ein Perl-Programm, das ich erbte, die eine riesige Datei (1 GB) analysieren und einen Hash der 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 hinzufügte, wenn sie verwendet wurden, schien der Speicherverbrauch nicht betroffen zu sein.

Das Skript war extrem langsam und so ein Speicher Schwein. Ich weiß, es war nicht gut entworfen, aber irgendwelche Ideen über den Hash-Speicherverbrauch?

Antwort

7

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.

See perlfaq3: How can I free an array or hash so my program shrinks?

Wenn der Speicher durch die Hash-Werte verwendet wird, ist eine übermäßige (d> physischen Speicher), könnten sie in eine Datei auf der Festplatte tie. 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 Disk Thrashing.)

11

Sie möchten vielleicht etwas wie DBM::Deep überprüfen. 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.

Auch, wenn Sie die Performance-Engpass aufzuspüren wollen Besuche Devel::NYTProf, die neuen Hotness in Perl Profilierung, die aus den New York Zeiten kamen.

5

Wenn Ihr Hash wirklich gigantisch ist, ist es wahrscheinlich eine bessere Strategie, einen Hashwert auf der Festplatte zu verwenden und das OS sich darum kümmern zu müssen, ob die Dinge in oder aus dem Speicher kommen. 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 Drop-in-Hash-Ersatz verwendet werden, aber beruht auf einem eigenen Format. Dies kann ein Schmerz sein, wenn Ihre Struktur von anderen (Nicht-Perl-) Systemen gelesen werden muss.

4

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 geöffnet 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 halten und vergleichen, während Sie gehen, und weiterspringen, bis sich die cmp ändert.

Ein anderer Ansatz könnte darin bestehen, 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 einspeisen.

Für allgemeinere Algorithmen können Sie nur vermeiden, für die Speichergröße zu zahlen, indem Sie es für die Kosten der Datenträgergeschwindigkeit handeln.

In den meisten Fällen gewinnt das Laden jeder Datenquelle in den Speicher nur während der Entwicklungszeit - dann zahlen Sie dafür in Footprint und/oder Geschwindigkeit, wenn N groß wird.

5

In Bezug auf die spezifische Frage: Nein, das Löschen von Hash-Schlüsseln reduziert nicht den Speicherverbrauch Ihres Programms.

In Bezug auf den allgemeineren Fall: Die überwiegende Mehrheit der Programme und Sprachen wird weiter auf Speicher halten, die sie zuvor verwendet haben, aber derzeit nicht verwenden. Dies liegt daran, dass die Anforderung der Speicherzuweisung durch das Betriebssystem eine relativ langsame Operation ist, so dass sie für den Fall, dass sie später erneut benötigt wird, beibehalten werden.

Also, wenn Sie diese Situation verbessern möchten, müssen Sie die maximale Speichermenge reduzieren, die von Ihrem Programm benötigt wird, indem Sie Ihre Algorithmen so anpassen, dass nicht mehr auf so viele Daten gleichzeitig zugegriffen werden muss -Diskettenspeicher (wie der oben 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.

4

Problemumgehung: Führen Sie einen untergeordneten Prozess aus, der den gesamten Arbeitsspeicher 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.