Grüße,Haskell ByteStrings - endend mit großen Datei bis in den Speicher geladen
Ich versuche zu verstehen, warum ich die gesamte Datei in den Speicher mit dem folgenden Programm geladen zu sehen bin, aber wenn Sie die Zeile aus kommentieren unten "(***)" dann läuft das Programm in konstantem (ungefähr 1,5M) Raum.
EDIT: Die Datei ist etwa 660 MB, das Feld in Spalte 26 ist eine Datumszeichenfolge wie '2009-10-01', und es gibt eine Million Zeilen. Der Prozess verwendet etwa 810 MB bis zum Zeitpunkt der 'getLine'
Habe ich recht in der Annahme, es ist mit der Aufspaltung der Zeichenfolge mit 'Split' verbunden, und dass irgendwie die zugrunde liegende ByteString, die aus der Datei gelesen wurde Wird kein Müll gesammelt, weil er immer noch referenziert wird? Aber wenn, dann dachte ich, BS.copy würde das umgehen. Irgendwelche Ideen, wie man die Berechnung erzwingt - ich kann nicht scheinen, Seq 'in den richtigen Platz zu bekommen, um einen Effekt zu haben.
(NB die Quelldatei durch Tabulatoren getrennte Linien)
Vielen Dank im Voraus,
Kevin
module Main where
import System.IO
import qualified Data.ByteString.Lazy.Char8 as BS
import Control.Monad
type Record = BS.ByteString
importRecords :: String -> IO [Record]
importRecords filename = do
liftM (map importRecord.BS.lines) (BS.readFile filename)
importRecord :: BS.ByteString -> Record
importRecord txt = r
where
r = getField 26
getField f = BS.copy $ ((BS.split '\t' txt) !! f)
loopInput :: [Record] -> IO()
loopInput jrs = do
putStrLn $ "Done" ++ (show $ last jrs)
hFlush stdout
x <- getLine
return()
-- (***)
loopInput jrs
main = do
jrs <- importRecords "c:\\downloads\\lcg1m.txt"
loopInput jrs
Es wäre hilfreich, die Datei oder zumindest einige Statistiken darüber zu haben. Ich bin nicht davon überzeugt, dass Ihr Problem nicht darin besteht, alle "[Record]" gleichzeitig im Speicher zu behalten (erzwungen durch den Aufruf "putStrLn ... last jrs"). Die gesamte Liste muss im Speicher bleiben, weil Sie sie in "loopInput" übergeben - wenn Sie nur "last jrs" übergeben haben oder wenn Sie nur den Kopf der Liste verbraucht haben, bevor Sie den Rest erzwingen, können Sie die inkrementelle Verarbeitung im konstanten Speicherbereich durchführen. EDIT: Auch einige Haufen Profilerstellung. –
Die Datei ist ungefähr 660 MB, das Feld in Spalte 26 ist eine Datumszeichenkette wie '2009-10-01', und es gibt eine Million Zeilen. Der Prozess benötigt ungefähr 810 MB, wenn er die 'getLine' erreicht. Prost! – Kevin