非常に大きな Unicode テキスト ファイル (6 GB 以上) を処理しようとしています。私が欲しいのは、それぞれのユニークな単語の頻度を数えることです。Data.Map
ファイルをトラバースするときに、各単語のカウントを追跡するために strict を使用します。プロセスに時間がかかりすぎ、メモリが多すぎます (20 GB 以上)。マップが巨大であると思われますが、ファイルのサイズの 5 倍に達するかどうかはわかりません! コードを以下に示します。私は次のことを試したことに注意してください:
Data.HashMap.Strict
の代わりに使用しData.Map.Strict
ます。Data.Map
メモリ消費の増加率が遅いという点でパフォーマンスが向上しているようです。ByteString
lazyの代わりに lazyを使用してファイルを読み取りますText
。そして、それを Text にエンコードして何らかの処理を行ってからByteString
、 forにエンコードし直し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"
私のアプローチの何が問題になっていますか?時間とメモリのパフォーマンスに関して、私がやろうとしていることを達成するための最良の方法は何ですか?