Mas*_*sse 9 io optimization file-io haskell
我有一些情况需要递归列出文件,但我的实现速度很慢.我有一个包含92784个文件的目录结构.find在不到0.5秒的时间内列出文件,但我的Haskell实现速度要慢得多.
我的第一个实现需要花费9秒多的时间来完成,下一个版本需要5秒多一点时间,我现在已经下降到不到两秒钟了.
listFilesR :: FilePath -> IO [FilePath]
listFilesR path = let
isDODD "." = False
isDODD ".." = False
isDODD _ = True
in do
allfiles <- getDirectoryContents path
dirs <- forM allfiles $ \d ->
if isDODD d then
do let p = path </> d
isDir <- doesDirectoryExist p
if isDir then listFilesR p else return [d]
else return []
return $ concat dirs
Run Code Online (Sandbox Code Playgroud)
该测试需要大约100兆字节的内存(+ RTS -s),并且该程序在GC中花费大约40%.
我正在考虑在WriterT monad中进行列表,将Sequence作为monoid来阻止concats和list创建.这有帮助吗?我还该怎么办?
编辑:我已经编辑了使用readDirStream的函数,它有助于保持内存不变.仍然有一些分配发生,但现在生产率> 95%,它运行不到一秒钟.
这是当前版本:
list path = do
de <- openDirStream path
readDirStream de >>= go de
closeDirStream de
where
go d [] = return ()
go d "." = readDirStream d >>= go d
go d ".." = readDirStream d >>= go d
go d x = let newpath = path </> x
in do
e <- doesDirectoryExist newpath
if e
then
list newpath >> readDirStream d >>= go d
else putStrLn newpath >> readDirStream d >>= go d
Run Code Online (Sandbox Code Playgroud)
我认为System.Directory.getDirectoryContents构建一个完整的列表,因此使用了很多内存.怎么用System.Posix.Directory? System.Posix.Directory.readDirStream逐个返回一个条目.
此外,FileManip库可能很有用,虽然我从未使用它.