Я пытаюсь обработать очень большой текстовый файл в формате Юникод (6 ГБ +). Я хочу рассчитать частоту каждого уникального слова. Я использую строгий Data.Map
для отслеживания отсчетов каждого слова, когда я пересекаю файл.
Процесс занимает слишком много времени и слишком много памяти (20 ГБ +). Я подозреваю, что карта огромна, но я не уверен, что она должна достигать 5-кратного размера файла!
Код показан ниже. Обратите внимание, что я попробовал следующее:
-
Использование
Data.HashMap.Strict
вместоData.Map.Strict
.Data.Map
, кажется, работает лучше с точки зрения более медленного увеличения потребления памяти. -
Чтение файлов с помощью ленивого
ByteString
вместо ленивогоText
. И затем я закодирую его в Text, сделав некоторую обработку, а затем верните его обратно вByteString
дляIO
.import Data.Text.Lazy (Text(..), cons, pack, append) import qualified Data.Text.Lazy as T import qualified Data.Text.Lazy.IO as TI import Data.Map.Strict hiding (foldr, map, foldl') import System.Environment import System.IO import Data.Word dictionate :: [Text] -> Map Text Word16 dictionate = fromListWith (+) . (`zip` [1,1..]) main = do [file,out] <- getArgs h <- openFile file ReadMode hO <- openFile out WriteMode mapM_ (flip hSetEncoding utf8) [h,hO] txt <- TI.hGetContents h TI.hPutStr hO . T.unlines . map (uncurry ((. cons '\t' . pack . show) . append)) . toList . dictionate . T.words $ txt hFlush hO mapM_ hClose [h,hO] print "success"
Что не так с моим подходом? Какой лучший способ выполнить то, что я пытаюсь сделать с точки зрения времени и производительности памяти?