Dies ist eigentlich eine Follow-up-Frage von diese Frage. Ich habe es geschafft, dass das Profiling funktioniert und das Problem scheint wirklich faul zu sein.
Die von mir verwendete Datenstruktur ist Map Int (Map Int Text)
, wobei Text
aus Data.Text stammt. Das Problem ist, dass die Funktion, die diese Map erstellt, einen riesigen Thunk erzeugt. Bei einem Eingabetext von ca. 3 MB benötigt das Programm mehr als 250 MB Speicher.
Nun zum eigentlichen Zweck dieser Frage:
Um die Anzahl der Zeichen in dieser Datenstruktur zu erhalten, verwenden Sie die folgende Funktion:
%Vor% Nicht schön, aber es macht die Arbeit erledigt. Ich verwende diese Funktion in der Hauptfunktion, direkt nachdem die TextResource erstellt wurde. Das Interessante ist, dass wenn ich das Programm mit der RTS-Option -hr
oder -hc
profiliere, die Speicherauslastung nach einiger Zeit auf 70 oder 50 MB sinkt, was völlig in Ordnung wäre.
Leider funktioniert das nur bei Verwendung der Profilierungsoptionen und der Funktion totalSize
- ohne sie ist es wieder 250 MB.
Ich habe das Programm (& lt; 70 Zeilen) zusammen mit einer Testdatei und einer Kabeldatei hochgeladen, so dass Sie es selbst ausprobieren können: Link
Die Datei test.xml ist eine generierte XML-Datei, die in das ausführbare Verzeichnis geschrieben werden sollte.
Zum Erstellen sollten cabal configure --enable-executable-profiling
und anschließend cabal build
ausreichen (wenn Sie die Profilierungsversionen der erforderlichen Bibliotheken installiert haben).
Sie können die Änderung sehen, wenn Sie das Programm einmal mit +RTS -hc
und einmal ohne.
Ich wäre wirklich großartig, wenn jemand das Programm ausführen könnte, da ich wirklich hier feststecke. Ich habe bereits versucht, deepseq
an mehreren Stellen einzufügen, aber nichts funktioniert (abgesehen von den Profilierungsoptionen).
Bearbeiten:
Das Profiling zeigt jedoch, dass nur ~ 20MB des Heaps verwendet werden, so dass ich in meinem Kommentar GHC dafür verantwortlich mache, nicht so viel von dem Kindergarten-Speicher zu befreien, wie Sie zu haben scheinen.
Danke, das hat mich in die richtige Richtung gelenkt. Wie sich herausstellt, können Sie GHC anweisen, eine Garbage Collection durchzuführen ( performGC ), was nach dem Erkunden der Karte sehr gut funktioniert. Obwohl ich denke, dass die Verwendung von performGC nicht empfohlen wird, scheint es das richtige Werkzeug für den Job hier zu sein.
Bearbeiten2: So habe ich die Hauptfunktion geändert (+ deepseqing die Rückgabe von BuildTextFile):
%Vor%Das Problem ist, dass die Funktion, die diese Map erstellt, einen riesigen Thunk erzeugt.
Nein. Basierend auf Heap-Profiling glaube ich nicht, dass die Raumnutzung Thunks ist. Außerdem habe ich Data.Map
durch strikte HashMaps ersetzt und die Map gezwungen (um zu vermeiden, dass große Thunks erzeugt werden) mit dem gleichen Ergebnis.
Wenn ich das Programm profiliere, indem ich die RTS-Option -hr oder -hc verwende, sinkt die Speicherbelegung nach einer Weile auf 70 oder 50 MB ab
Ich kann das nicht reproduzieren. Mit -hr
, -hy
oder -hc
behält der Prozess einen 140-MB-Heap bei. Profiling zeigt jedoch, dass nur ~ 20MB des Heaps verwendet werden, so dass ich in meinem Kommentar GHC dafür verantwortlich mache, nicht so viel GC-Speicher wie Sie zu haben scheinen.
Was den hohen Speicherverbrauch während der Berechnung anbelangt, zeigt das obige -hy
-Profil an, dass der meiste Speicher auf den String
-Typ und die HaXML-Bibliothek Posn
-Typ zurückzuführen ist. Ich wiederhole meinen Vorschlag, nach einer ByteString
oder Text
basierten XML-Bibliothek zu suchen, die ressourcenschonender ist (xml-enumerator?).
Tags und Links haskell memory-profiling