【发布时间】:2011-03-24 13:08:14
【问题描述】:
我正在尝试使用 Haskell 处理大文件。我想逐字节浏览输入文件,并逐字节生成输出。当然,我需要用合理大小(几 KB)的块来缓冲 IO。我做不到,我需要你的帮助。
import System
import qualified Data.ByteString.Lazy as BL
import Data.Word
import Data.List
main :: IO ()
main =
do
args <- System.getArgs
let filename = head args
byteString <- BL.readFile filename
let wordsList = BL.unpack byteString
let foldFun acc word = doSomeStuff word : acc
let wordsListCopy = foldl' foldFun [] wordsList
let byteStringCopy = BL.pack (reverse wordsListCopy)
BL.writeFile (filename ++ ".cpy") byteStringCopy
where
doSomeStuff = id
我将此文件命名为TestCopy.hs,然后执行以下操作:
$ ls -l *MB
-rwxrwxrwx 1 root root 10000000 2011-03-24 13:11 10MB
-rwxrwxrwx 1 root root 5000000 2011-03-24 13:31 5MB
$ ghc --make -O TestCopy.hs
[1 of 1] Compiling Main ( TestCopy.hs, TestCopy.o )
Linking TestCopy ...
$ time ./TestCopy 5MB
real 0m5.631s
user 0m1.972s
sys 0m2.488s
$ diff 5MB 5MB.cpy
$ time ./TestCopy 10MB
real 3m6.671s
user 0m3.404s
sys 1m21.649s
$ diff 10MB 10MB.cpy
$ time ./TestCopy 10MB +RTS -K500M -RTS
real 2m50.261s
user 0m3.808s
sys 1m13.849s
$ diff 10MB 10MB.cpy
$
我的问题:5MB 和 10MB 文件之间存在巨大差异。我希望性能与输入文件的大小成线性关系。请问我做错了什么,我该如何做到这一点?我不介意使用惰性字节串或其他任何东西,只要它可以工作,但它必须是标准的 ghc 库。
Precision:适用于大学项目。而且我不是要复制文件。 doSomeStuff 函数将执行我必须自定义的压缩/解压缩操作。
【问题讨论】:
-
ByteString 的
pack和unpack是非常昂贵的操作。你不能doSomeStuff直接用ByteString 吗?注意:惰性 ByteString 在内部被“缓冲”,这可能足以满足您的任务 -
我只是在没有打包和解包的情况下尝试过,直接处理字节串,结果更长,但我仍然在 5MB 和 10MB 之间有这么大的差异。
-
也许您可以在某处发布一个完整的代码示例来演示问题?
-
@Ed'ka 但这就是我所做的。上面 TestCopy.hs 的工作代码说明了这个问题,因为 10MB 的文件在 3 分钟内被复制。
-
cabal unpack blaze-builder-- 现在您有了源代码,可以将您需要的任何文件直接移动到您的存储库中。
标签: io lazy-evaluation bytestring haskell