【问题标题】:How to write big file efficiently in Haskell如何在 Haskell 中高效地写入大文件
【发布时间】:2019-08-02 20:13:21
【问题描述】:

您好,我正在尝试及时编写~1GB 文件。有没有推荐的方法。到目前为止,该过程大约需要几十分钟。我在使用Text 时错了我应该使用ByteString 吗? (我也用过String

    pt="d:\\data2.csv"
    cnt=400000000

    main::IO()
    main=do
        let payload=dat
        writeWithHandle pt dat


    dat::Text
    dat=Data.Text.pack "0744442339"


    writeWithHandle::FilePath->Text->IO()
    writeWithHandle path tx=do
        handle<-openFile path WriteMode
        writeTimes cnt handle dat

    writeTimes::Int->Handle->Text->IO()
    writeTimes cnt handle payload= forM_ ([0..cnt])  (\x->Data.Text.IO.hPutStrLn handle payload)

我不明白为什么要花几十分钟的时间。最初我使用的是writeFile,但我认为这意味着要为每一行不断打开和关闭file,所以我使用了@987654328 @ 无济于事。

【问题讨论】:

  • 批量写入会更快吗? T.replicate 10 dat 甚至 1000x 之类的东西。
  • 您是否在打开优化的情况下进行编译?在我的机器上写一个 14GB 的文件或多或少需要我大约 5 分钟。 (另外,您在写入文件后忘记关闭文件,您应该只使用withFile 而不是openFile tbh)
  • 我没有打开优化编译。 (我还是个初学者)。
  • 使用字节串并进行优化,您的代码在 43 秒内创建了一个 4GB 的文件。这里的一个主要问题是Text 存储为 UTF16 而文件输出通常是 UTF8,因此转换需要一些时间。构建一个字节串一次,我只为整个程序转换了一次dat。然而,在现实世界的场景中,您可能有很多不同的线路。如果跳过Text 是一种选择,我会尝试这样做。
  • 显然在我关闭 handle 之后,它的工作速度要快得多,正如 @Cubic 指出的那样。

标签: performance haskell io writefile


【解决方案1】:

我建议为此使用 Builder,这是一种填充缓冲区的有效方法,并且可以直接写入 Handle。

#!/usr/bin/env stack
-- stack --resolver ghc-8.6.4 script
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString.Builder (Builder, hPutBuilder)
import Data.Foldable (fold)
import System.IO (IOMode (WriteMode), withBinaryFile)

pt :: FilePath
pt = "data2.csv"

cnt :: Int
cnt = 400000000

main :: IO ()
main = writeWithHandle pt dat

dat :: Builder
dat = "0744442339"

writeWithHandle :: FilePath -> Builder -> IO ()
writeWithHandle path tx =
  withBinaryFile path WriteMode $ \h ->
  hPutBuilder h $ makeBuilder cnt tx

makeBuilder :: Int -> Builder -> Builder
makeBuilder cnt payload = fold $ replicate cnt $ payload <> "\n"

如果您愿意,可以将payload 保留为Text 值,然后使用encodeUtf8Builder 转换为Builder

【讨论】:

  • dat :: Builder; dat = "0744442339" 是如何工作的?在 GHCi 中,同样会遇到错误Couldn't match expected type ‘Builder’ with actual type ‘[Char]’
猜你喜欢
  • 2018-07-08
  • 2011-03-25
  • 1970-01-01
  • 2013-11-19
  • 1970-01-01
  • 2014-01-26
  • 2020-05-18
  • 2014-03-28
  • 1970-01-01
相关资源
最近更新 更多