【发布时间】:2010-10-07 12:56:41
【问题描述】:
我有一些需要递归列出文件的情况,但我的实现速度很慢。我有一个包含 92784 个文件的目录结构。 find 在不到 0.5 秒的时间内列出文件,但我的 Haskell 实现要慢很多。
我的第一个实现需要 9 多秒才能完成,下一个版本需要 5 多秒,而我目前只用了不到 2 秒。
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
测试占用大约 100 兆内存 (+RTS -s),程序在 GC 上花费了大约 40%。
我正在考虑在 WriterT monad 中使用 Sequence 作为 monoid 进行列表,以防止 concats 和列表创建。这可能有帮助吗?我还应该做什么?
编辑:我已经编辑了函数以使用 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
【问题讨论】:
标签: optimization haskell file-io io