Haskell如何编写大型字符串

3

你好,Stackoverflow社区。

我相对来说是Haskell的新手,并且我注意到使用writeFilehPutStr将大字符串写入文件非常缓慢。

对于一个1.5MB的字符串,我的程序(使用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"

with 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

也许你们可以帮我加快速度。

提前感谢。


字符串包含什么内容?如果您可以对ByteString进行廉价转换,那么它的写入速度就会非常快。 - Daniel Fischer
2
我不相信写文件与此有任何关系;在这里,main = readFile "1.5mb.txt" >>= writeFile "1.5mb2.txt" 只需要 0m0.089s,而不是你所报告的 C++ 的 2 秒,因此更快。当文件大小约为 50 MB 时,它开始接近 2 秒;同样,writeFile "big.txt" (show [1..250000]) 只需 0.06 秒,并生成一个 1.6 mb 的文件。 - applicative
你说得对,@applicative,我的问题似乎出在其他地方。我将发布一些代码。 - The Dude
1
请提供足够的代码,以便我们可以编译、运行并观察两秒钟的暂停。 - Daniel Wagner
2个回答

2
是的。例如,您可以使用模块Data.Text或Data.Text.Lazy中的Text类型,它们在内部以比字符列表更高效的方式(即UTF-16)表示文本。
当编写二进制数据(可能包含某种形式的文本编码)时,可以使用ByteStrings或其惰性版本。
在修改Text或ByteStrings时,一些修改操作在惰性版本上更快。如果您只想在创建字符串后从中读取,则通常建议使用非惰性版本。

2

这是一个众所周知的问题。默认的Haskell String 类型是简单的 [Char],根据定义很慢,并且如果它被惰性构造(通常情况下),那么速度就会非常慢。然而,作为列表,它允许使用列表组合器进行简单和清晰的处理,并且在不需要考虑性能时非常有用。如果需要考虑性能,则应使用 ByteStringText 包。由于 ByteString 随着ghc一起发布,因此更好,但不提供Unicode支持。基于 ByteString 的utf8包可在hackage上获得。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接