假设我有几个200mb +的文件需要grep。我如何在Haskell中做到这一点?解析Haskell中的大日志文件
这里是我的初步方案:
import Data.List
import Control.Monad
import System.IO
import System.Environment
main = do
filename <- liftM head getArgs
contents <- liftM lines $ readFile filename
putStrLn . unlines . filter (isPrefixOf "import") $ contents
这读取整个文件到内存中,通过分析它之前。 然后我带着这样的:
import Data.List
import Control.Monad
import System.IO
import System.Environment
main = do
filename <- liftM head getArgs
file <- (openFile filename ReadMode)
contents <- liftM lines $ hGetContents file
putStrLn . unlines . filter (isPrefixOf "import") $ contents
我想既然hGetContents
很懒,it will avoid reading the whole file into memory。但是,在valgrind
下运行这两个脚本都显示出类似的内存使用情况。所以无论我的脚本是错误的,还是valgrind
都是错误的。我编译脚本使用
ghc --make test.hs -prof
我错过了什么?奖金问题:我看到很多关于如何在Haskell中使用惰性IO实际上是一件坏事的提及。如何/为什么我会使用严格的IO?
更新:
所以看起来我错了,我的valgrind的读数。使用+RTS -s
,这里就是我得到:
7,807,461,968 bytes allocated in the heap
1,563,351,416 bytes copied during GC
101,888 bytes maximum residency (1150 sample(s))
45,576 bytes maximum slop
2 MB total memory in use (0 MB lost due to fragmentation)
Generation 0: 13739 collections, 0 parallel, 2.91s, 2.95s elapsed
Generation 1: 1150 collections, 0 parallel, 0.18s, 0.18s elapsed
INIT time 0.00s ( 0.00s elapsed)
MUT time 2.07s ( 2.28s elapsed)
GC time 3.09s ( 3.13s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 5.16s ( 5.41s elapsed)
的重要行是101,888 bytes maximum residency
,它说,在任何给定的点我的脚本使用的内存101 KB最多。我掠过的文件是44 MB。所以我认为判决是:readFile
和hGetContents
都是懒惰的。
后续问题:
为什么我看到的内存7GB在堆上分配?对于在44 MB文件中读取的脚本,这看起来非常高。
更新后续问题
貌似的堆上分配的内存数GB的不是非典型哈斯克尔,关注所以没有原因。使用替代String
小号ByteString
S可内存使用率下降了不少:
81,617,024 bytes allocated in the heap
35,072 bytes copied during GC
78,832 bytes maximum residency (1 sample(s))
26,960 bytes maximum slop
2 MB total memory in use (0 MB lost due to fragmentation)
哼,你确定在用'putStrLn'实际编写之前不需要建立整个'unlines'字符串吗?我会尝试像'Control.Monad.forM_(过滤器(isPrefixOf“导入”)内容)$ putStrLn'。然而,这只是一个猜测。 – 2012-03-17 01:19:32
@Riccardo:不,可以懒惰评估'unlines'。在'ghci'中试试'putStr $ unlines $ map show [1 ..]'。 – ephemient 2012-03-17 01:28:20
-O2神奇地解决了这个问题? – gspr 2012-03-17 07:55:13