haskell写大字符串
大家好,我的社区 我对Haskell比较陌生,我注意到用haskell写大字符串,haskell,Haskell,大家好,我的社区 我对Haskell比较陌生,我注意到用 writeFile或hPutStr非常慢 对于1.5MB的字符串,我的程序(用ghc编译)大约需要2秒钟,而 C++中的“相同”代码只需0.1秒。 该字符串由一个包含大约10000个元素的列表生成,然后用writeFile转储。我还尝试使用mapM和hPutStr遍历列表,结果相同 有没有写大字符串的更快的方法 更新 正如@applicative所指出的,下面的代码很快就会以2MB文件结束 main = readFile "input.t
writeFile
或hPutStr
非常慢
对于1.5MB的字符串,我的程序(用ghc编译)大约需要2秒钟,而
C++中的“相同”代码只需0.1秒。
该字符串由一个包含大约10000个元素的列表生成,然后用writeFile
转储。我还尝试使用mapM
和hPutStr
遍历列表,结果相同
有没有写大字符串的更快的方法
更新
正如@applicative所指出的,下面的代码很快就会以2MB文件结束
main = readFile "input.txt" >>= writeFile "ouput.txt"
所以我的问题似乎在别的地方。下面是我的两个实现
编写列表(WordIndex和CoordList是映射和列表的类型别名)
使用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"
也许你们能帮我找到一个加速点
提前谢谢是的。例如,您可以使用模块
Data.Text
或Data.Text.Lazy
中的Text
类型,它们在内部以比字符列表更有效的方式表示文本(即UTF-16)
在编写二进制数据(可能包含也可能不包含以某种形式编码的文本)时,可以使用ByteString
s或它们的等价物
当修改
文本
或ByteStrings
时,在惰性版本上修改它们的一些操作会更快。如果您只想在创建字符串后读取该字符串,通常建议使用非惰性版本。这是一个众所周知的问题。默认的HaskellString
类型是simple[Char]
,根据定义,它的速度很慢,如果它是惰性构造的(通常情况下),则它的速度非常慢。然而,作为列表,它允许使用列表组合器进行简单而干净的处理,并且在性能不是问题时非常有用。如果是,则应使用ByteString
或Text
包ByteString
更好,因为它与ghc一起提供,但不提供unicode支持<基于代码>ByteString的utf8软件包在hackage上提供 字符串包含什么类型的内容ByteString
的写入速度是最快的,所以如果你能便宜地转换成ByteString
,那将是一种选择<代码>主文件=“读文件”“1.5 Mb.txt”> =写文件“1.5 Mb2.txt”<代码>使用<代码> 0M0.089S 这里,不是2秒,因此比您报告的C++更快。在大约50MB时,它开始接近2秒;类似地,writeFile“big.txt”(show[1..250000])
需要0.06秒,生成一个1.6MB的文件。你是对的@applicative我的问题似乎在其他地方。我将发布一些代码请提供足够的代码,我们可以编译、运行并观察两秒钟的暂停。
-- 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