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"

所以我的问题似乎出在其他地方。这是我编写列表的两个实现(WordIndex 和 CoordList 是 Map 和 List 的类型别名)

使用 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],根据定义很慢,如果它是惰性构造的(通常情况下),则速度很慢。但是,作为列表,它允许使用列表组合器进行简单而干净的处理,并且在性能不是问题时很有用。如果是,则应使用ByteStringText打包。ByteString更好,因为它与 ghc 一起提供,但不提供 unicode 支持。ByteStringhackage 上提供了基于 utf8 的软件包。

于 2012-07-10T19:56:49.310 回答
2

是的。例如,您可以使用Text模块中的类型Data.Textor Data.Text.Lazy,它在内部以比 Chars 列表更有效的方式(即 UTF-16)表示文本。

在编写二进制数据(可能包含也可能不包含以某种形式编码的文本)时,您可以使用ByteStrings 或它们的惰性等效项。

修改TextorByteStrings时,一些修改它们的操作在惰性版本上更快。如果您只想在创建这样的字符串后读取它,通常可以推荐非惰性版本。

于 2012-07-10T19:33:50.587 回答