3

こんにちは Stackoverflow コミュニティです。

私はHaskellに比較的慣れていないので、ファイルに大きな文字列を書き込む writeFileか、非常にhPutStr遅いことに気付きました。

1.5 Mb 文字列の場合、私のプログラム (ghc でコンパイル) は約 2 秒かかりますが、c++ の「同じ」コードは約 0.1 秒しかかかりません。文字列は、約 10000 個の要素を持つリストから生成され、 でダンプされwriteFileます。また、リストをトラバースしようとしましたがmapM_hPutStr同じ結果が得られました。

大きな文字列をより速く書く方法はありますか?

アップデート

@applicativeが指摘したように、次のコードは2MBのファイルですぐに終了します

main = readFile "input.txt" >>= writeFile "ouput.txt"

だから私の問題はどこかにあるようです。リストを書くための私の2つの実装は次のとおりです(WordIndexとCoordListはMapとListのtypealiasesです)

hPutStrLn で

-- Print to File
indexToFile :: String -> WordIndex -> IO ()
indexToFile filename index =
    let 
        indexList = map (\(k, v) -> entryToString k v)  (Map.toList index)
    in do
        output <- openFile filename WriteMode
        mapM_ (\v -> hPutStrLn output v) indexList
        hClose output


-- Convert Listelement to String
entryToString :: String -> CoordList -> String
entryToString key value = (embedString 25 key) ++ (coordListToString value) ++ "\n"

writeFile で

-- Print to File
indexToFile :: String -> WordIndex -> IO ()
indexToFile filename index = writeFile filename (indexToString "" index)

-- Index to String
indexToString :: String -> WordIndex -> String
indexToString lead index = Map.foldrWithKey (\k v r -> lead ++ (entryToString k v) ++ r) "" index

ここでスピードアップを見つけるのに少し手伝ってくれるかもしれません。

前もって感謝します

4

2 に答える 2

2

これはよく知られた問題です。デフォルトの HaskellString型は単純[Char]で、定義上遅く、遅延して構築された場合 (通常の状況) は非常に遅くなります。ただし、リストとしては、リスト コンビネータを使用したシンプルでクリーンな処理が可能で、パフォーマンスが問題にならない場合に役立ちます。そうであれば、ByteStringまたはTextパッケージを使用する必要があります。ByteStringghc に同梱されているため、より優れていますが、Unicode サポートは提供していません。ByteStringベースの utf8 パッケージは hackage で入手できます。

于 2012-07-10T19:56:49.310 に答える
2

はい。たとえば、TextモジュールData.Textorの型を使用できData.Text.Lazyます。これらは、Char のリストよりも効率的な方法 (つまり、UTF-16) でテキストを内部的に表します。

バイナリ データ (何らかの形式でエンコードされたテキストを含む場合と含まない場合があります) を書き込む場合、ByteStrings またはそれらの遅延等価物を使用できます。

Textまたはを変更するByteStrings場合、それらを変更する一部の操作は遅延バージョンの方が高速です。そのような文字列を作成した後にその文字列から読み取るだけの場合は、通常、遅延のないバージョンをお勧めします。

于 2012-07-10T19:33:50.587 に答える