¿Cómo enumerar directorios más rápido?

Tengo algunas situaciones en las que necesito enumerar archivos de forma recursiva, pero mis implementaciones han sido lentas. Tengo una estructura de directorio con 92784 archivos.find enumera los archivos en menos de 0,5 segundos, pero mi implementación de Haskell es mucho más lenta.

Mi primera implementación tardó un poco más de 9 segundos en completarse, la próxima versión un poco más de 5 segundos y actualmente tengo menos de dos segundos.

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

La prueba toma alrededor de 100 megabytes de memoria (+ RTS -s), y el programa gasta alrededor del 40% en GC.

Estaba pensando en hacer el listado en una mónada WriterT con Sequence como el monoide para evitar los concatos y la creación de listas. ¿Es probable que esto ayude? ¿Que más deberia hacer?

Editar: He editado la función para usar readDirStream, y ayuda a mantener baja la memoria. Todavía está sucediendo alguna asignación, pero la tasa de productividad es> 95% ahora y se ejecuta en menos de un segundo.

Esta es la versión actual:

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 

Respuestas a la pregunta(4)

Su respuesta a la pregunta