私はUTF8で大きなテキストファイルをロードして解析しなければならなかったHaskellのプログラムを書いています。このファイルは、各行にkey:valueのペアを持つ辞書を表します。私のプログラムでは、辞書検索を高速化するためのData.Mapコンテナが必要です。私のファイルは約40MBですが、私のプログラムにロードした後、1.5GBのRAMが使用され、決して解放されません。私は何を間違えたのですか?メモリ使用量は予想されますか?ここで なぜHaskellは文字列を扱うときに膨大なメモリを割り当てるのですか?
は私のプログラムからのコードサンプルです:import Engine
import Codec.Archive.Zip
import Data.IORef
import System.IO
import System.Directory
import qualified System.IO.UTF8 as UTF8
import qualified Data.ByteString.Lazy as B
import qualified Data.ByteString.UTF8 as BsUtf
import qualified Data.Map as Map
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Glade
maybeRead :: Read a => BsUtf.ByteString -> Maybe a
maybeRead s = case reads $ BsUtf.toString s of
[(x, "")] -> Just x
_ -> Nothing
parseToEntries :: [BsUtf.ByteString] -> [(BsUtf.ByteString, Int)]
parseToEntries [] = []
parseToEntries (x:xs) = let (key, svalue) = BsUtf.break (==':') x
value = maybeRead svalue
in case value of
Just x -> [(key, x)] ++ parseToEntries xs
Nothing -> parseToEntries xs
createDict :: BsUtf.ByteString -> IO (Map.Map BsUtf.ByteString Int)
createDict str = do
let entries = parseToEntries $ BsUtf.lines str
dict = Map.fromList entries
return (dict)
main :: IO()
main = do
currFileName <- newIORef ""
dictZipFile <- B.readFile "data.db"
extractFilesFromArchive [] $ toArchive dictZipFile
dictFile <- UTF8.readFile "dict.txt"
dict <- createDict $ BsUtf.fromString dictFile
...
searchAccent :: Map.Map BsUtf.ByteString Int -> String -> Int
searchAccent dict word = let sword = BsUtf.fromString $ map toLower word
entry = Map.lookup sword dict
in case entry of
Nothing -> -1
Just match -> 0
私はHaskellの上で少しさびだけど、短所のオペレータがどことしてIIRC、 '++'構文は、メモリ・高価です( ':')安いです。 '(key、x):parseToEntries xs'のようなものを使うことは可能ですか?もう一度。 。 。私のハスケルは非常に錆びているので、これは邪魔になるかもしれません。 – jpm
@jpmの場合、メモリの使用量は '++'の最初の引数の長さに依存します。この場合、関係はありません。 –
@maxtaldykinああ、意味がある。説明をありがとう。 – jpm