2009-11-23 20 views
5

Hemos encontrado un problema de rendimiento inesperado al recorrer directorios en busca de archivos utilizando un patrón de comodín.Win32 API FindFirstFile y FindNextFile rendimiento frente a la línea de comandos

Tenemos 180 carpetas cada una con 10.000 archivos. Una búsqueda en línea de comandos usando dir <pattern> /s se completa casi al instante (< 0,25 segundos). Sin embargo, desde nuestra aplicación, la misma búsqueda demora entre 3 y 4 segundos.

Inicialmente hemos intentado utilizar System.IO.DirectoryInfo.GetFiles() con SearchOption.AllDirectories y ahora hemos probado las llamadas a la API de Win32 FindFirstFile() y FindNextFile().

Hacer un perfil de nuestro código utilizando indica que la gran mayoría del tiempo de ejecución se utiliza en estas llamadas.

Nuestro código se basa en la siguiente entrada en el blog:

http://codebetter.com/blogs/matthew.podwysocki/archive/2008/10/16/functional-net-fighting-friction-in-the-bcl-with-directory-getfiles.aspx

Encontramos que esto es lento por lo que la función de actualización GetFiles tomar un patrón string de búsqueda en lugar de un predicado.

¿Alguien puede arrojar alguna luz sobre lo que podría estar mal con nuestro enfoque?

+0

¿qué estás utilizando para hacer la búsqueda desde la línea de comandos? ¿Podría ser que esté usando los índices de búsqueda de Windows para hacer la consulta en lugar de recorrer cada archivo? –

+0

@Matt solo estamos haciendo un 'dir/s' (he actualizado mi publicación en consecuencia). –

+1

Suena sospechoso. Dudo seriamente que "dir" use cualquier otra cosa, excepto FindFirstFile/FindNextFile también. Tal vez los malgastes. ¿Podría proporcionar un fragmento que ilustre cómo los usa? – sharptooth

Respuesta

2

Puede probar con una implementación de FindFirstFile y FindNextFile I una vez blogged acerca de.

+0

Nuestro enfoque es muy similar al de Darin –

+0

He probado mi solución y se necesitan 230 milisegundos para enumere un directorio que contenga> 100K archivos. –

+0

Se puede lograr una aceleración adicional con 'FindFirstFileEx (... FindExInfoBasic ...)' – MSalters

0

Pruebe IShellFolder::EnumObjects con SHGetDataFromIDList/IShellFolder::GetAttributesOf.

Pro/Cons here.

7

En mis pruebas con FindFirstFileEx con FindExInfoBasic y FIND_FIRST_EX_LARGE_FETCH es mucho más rápido que la llanura FindFirstFile.

Escanear 20 carpetas con ~ 300,000 archivos tomó 661 segundos con FindFirstFile y 11 segundos con FindFirstFileEx. Las llamadas posteriores a las mismas carpetas tomaron menos de un segundo.

HANDLE h = FindFirstFileEx (search.c_str(), FindExInfoBasic, & data, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);

Cuestiones relacionadas