Как быстрее составить список каталогов?

У меня есть несколько ситуаций, когда мне нужно перечислить файлы рекурсивно, но мои реализации были медленными. У меня есть структура каталогов с 92784 файлами. find выводит список файлов менее чем за 0,5 секунды, но моя реализация Haskell намного медленнее.

Моя первая реализация заняла чуть более 9 секунд, следующая версия - чуть более 5 секунд, и я ' m в настоящее время составляет чуть менее двух секунд.

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% на сборщик мусора.

Я думал сделать листинг в монаде WriterT с Sequence в качестве моноида, чтобы предотвратить конкатенацию и создание списка. Это может помочь? Что еще мне делать?

Edit: Я отредактировал функцию, чтобы использовать 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 
9
задан Don Stewart 24 April 2011 в 16:25
поделиться