Как быстрее составить список каталогов?
У меня есть несколько ситуаций, когда мне нужно рекурсивно перечислять файлы, но мои реализации были медленными. У меня есть структура каталогов с 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
Тест занимает около 100 мегабайт памяти (+ RTS-s), и программа тратит около 40% в GC.
Я думал о том, чтобы сделать листинг в монаде WriterT с Sequence в качестве моноида, чтобы предотвратить создание конкататов и списков. Это вероятно, это помогает? Что еще я должен сделать?
Редактировать: Я отредактировал функцию, чтобы использовать 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