4

私はHaskellでプログラムを作成しました。このプログラムは、UTF8で大きなテキストファイルをロードして解析する必要がありました。このファイルは、各行にキーと値のペアがある辞書を表します。私のプログラムでは、高速辞書検索用のData.Mapコンテナーが必要です。私のファイルは約40MBですが、プログラムにロードした後、1.5 GBのRAMが使用され、解放されることはありません。私は何を間違えましたか?メモリ使用量は予想されますか?

これが私のプログラムのコードサンプルです:

モジュールメインここで

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                       
4

2 に答える 2

7

素早い回答。
主な問題は、System.IO.UTF8.readFileファイルをに読み込むことですString

想定されるボトルネックは次のとおりです。

dictFile <- UTF8.readFile "dict.txt"
dict <- createDict $ BsUtf.fromString dictFile

UTF-8 テキストを扱う場合は、Data.Textの代わりに使用することをお勧めしますByteString。次のようなことを試してください:

import qualified Data.Text.Lazy as LT
import qualified Data.Text.Lazy.Encoding as LT

...
dictFile <- B.readFile "dict.txt"
dict <- createDict $ LT.decodeUtf8 dictFile

もう 1 つのボトルネックは、数値の解析ByteStringです。使用する方が良いです:StringreadData.Text.Lazy.Read

import qualified Data.Text.Lazy.Read as LT

maybeRead :: LT.Text -> Maybe Int
maybeRead s = case LT.decimal s of
    Left _  -> Nothing
    Right i -> Just i
于 2012-04-05T21:39:19.957 に答える
4

HaskellString型は間接的な (怠惰のため) 文字のリンクされたリストです。スペース的に非常に無駄です。大量のテキストについては、代わりにData.Text( http://hackage.haskell.org/package/textから)試してみることをお勧めします。

ソースがアップしたので、文字列がByteStringではなく遅延していることがわかったStringので、これは関係ありません。プロファイリングは次のステップです。)

于 2012-04-05T21:31:43.220 に答える