2011-09-15 11 views
5

Necesito leer el contenido de varios miles de archivos pequeños al inicio. En Linux, solo usar fopen y leer es muy rápido. En Windows, esto sucede muy lentamente.Cómo crear CreateFile lo más rápido posible

He cambiado al uso de E/S superpuestas (E/S asíncrona) usando ReadFileEx, donde Windows hace una devolución de llamada cuando los datos están listos para leer.

Sin embargo, los miles reales de llamadas a CreateFile en sí siguen siendo un cuello de botella. Tenga en cuenta que proporciono mis propios búferes, enciendo el indicador NO_BUFFERING, le doy la sugerencia de SERIAL, etc. Sin embargo, las llamadas a CreateFile toman varios 10 segundos, mientras que en Linux todo se hace mucho más rápido.

¿Hay algo que se pueda hacer para que estos archivos estén listos para leer más rápido?

La llamada a CreateFile es:

  hFile = CreateFile(szFullFileName, 
       GENERIC_READ, 
       FILE_SHARE_READ | FILE_SHARE_WRITE, 
       NULL, 
       OPEN_EXISTING, 
       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN, 
       NULL); 
+1

Es posible que el cuello de botella sea el sistema de archivos, ¿es posible usar un archivo plano en lugar de leer miles de archivos pequeños? – tenfour

+0

Windows es notoriamente malo al tratar con una gran cantidad de archivos en un directorio, si ese es tu caso. ¿Es multithreading la cosa una opción, por lo que tendrá 10 hilos haciendo las lecturas en concur? – eran

+1

Debería echarle un vistazo a esta pregunta http://stackoverflow.com/questions/197162/ntfs-performance-and-large-volumes-of-files-and-directories –

Respuesta

9

CreateFile en kernel32.dll tiene cierta sobrecarga adicional en comparación con el kernel syscall NtCreateFile en ntdll.dll. Esta es la verdadera función que CreateFile llama para solicitar al kernel que abra el archivo. Si necesita abrir una gran cantidad de archivos, NtOpenFile será más eficiente al evitar los casos especiales y la traducción de rutas que Win32 tiene, cosas que no se aplicarían a un grupo de archivos en un directorio de todos modos.

NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT HANDLE *FileHandle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes, OUT IO_STATUS_BLOCK *IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions); 

HANDLE Handle; 
OBJECT_ATTRIBUTES Oa = {0}; 
UNICODE_STRING Name_U; 
IO_STATUS_BLOCK IoSb; 

RtlInitUnicodeString(&Name_U, Name); 

Oa.Length = sizeof Oa; 
Oa.ObjectName = &Name_U; 
Oa.Attributes = CaseInsensitive ? OBJ_CASE_INSENSITIVE : 0; 
Oa.RootDirectory = ParentDirectoryHandle; 

Status = NtOpenFile(&Handle, FILE_READ_DATA, &Oa, &IoSb, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SEQUENTIAL_ONLY); 

Principal inconveniente: esta API no es compatible con Microsoft para su uso en modo de usuario. Dicho esto, la función equivalente is documented for kernel mode use y no ha cambiado desde la primera versión de Windows NT en 1993.

NtOpenFile también le permite abrir un archivo con relación a un gestor de directorio existente (ParentDirectoryHandle en el ejemplo) que debe reducir en algunos de los gastos generales del sistema de archivos al ubicar el directorio.

Al final, NTFS puede ser demasiado lento en el manejo de directorios con grandes cantidades de archivos como dijo Carey Gregory.

+0

Tampoco la afirmación sobre NTFS es "lenta" ni la de NtCreateFile es más rápida que CreateFile true; ambas están totalmente inventadas.A menos que alguien publique alguna prueba de eso, tendré que llamar mierda, excepto por unos pocos ciclos de CPU, ambas funciones se comportarán idénticas a las de la noche y NTFS es un sistema de archivos moderadamente rápido. – specializt

+0

Ver http://stackoverflow.com/questions/197162/ntfs-performance-and-large-volumes-of-files-and-directories –

+0

Sí ... eso no es prueba alguna. Sin datos. – specializt

0

Intente buscar en la MFT de manera eficiente antes de emitir el archivo Crear. Esto se puede hacer emitiendo FSCTL_ENUM_USN_DATA.

Cuestiones relacionadas