Enumeración de discos y listado de archivos -- ++ campo con recursion campo con file-system campo con windows campo con winapi camp codereview Relacionados El problema

Disk enumeration and file listing


5
vote

problema

Español

Estoy escribiendo código C ++ para enumerar todo el listado HDD y unidad. Sin embargo, se tarda más de 15 minutos en completar la enumeración del disco de todas las unidades (capacidad de disco duro de 500 GB) y compilar la respuesta en un archivo binario.

Sin embargo, tengo un ejecutable de terceros que me da la lista de todo el disco en menos de dos minutos. ¿Puedes consultar mi código y sugerir algunas técnicas de mejora de rendimiento?

  [1,2,3]5  
Original en ingles

I am writing C++ code to enumerate the whole HDD and drive listing. However, it takes more than 15 minutes to complete the disk enumeration of all drives (HDD capacity of 500GB) and compile the response in a binary file.

However, I have a 3rd party executable which gives me the listing of the whole disk in just less than two minutes. Can you please look into my code and suggest some performance improvement techniques?

EnumFiles(CString FolderPath, CString SearchParameter,WIN32_FIND_DATAW *FileInfoData) {          CString SearchFile = FolderPath + SearchParameter;          CString FileName;          hFile = FindFirstFileW(SearchFile, FileInfoData); //   \\?\C:\*              if (hFile == INVALID_HANDLE_VALUE)             {                 // Error             }           else          {                 do                 {                     FileName = FileInfoData->cFileName;                      if (FileInfoData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)                     {                         if (! (FileName == L"." || FileName == L".."))                         {                                         // Save the Folder Information                           EnumFiles(FolderPath + FileName +(L"\\"), SearchParameter,FileInfoData);                         }                     }                     else                    {                      // Save the File Parameters                      }                     } while (FindNextFileW(hFile, FileInfoData)); }            FindClose(hFile);        } 
              
   
   

Lista de respuestas

6
 
vote

¿Puedes consultar mi código y sugerirme algunas técnicas de mejora de rendimiento?

no - no funciona así. Si bien hay algunas cosas obvias que puede capturar visualmente (como observar las comparaciones de cadenas en cada iteración) cada vez que se optimice, debe comenzar a perfilar su Ejecución, luego aislando las partes que se apoderan de la mayor hora, luego optimizando, luego perfilando nuevamente.

Por ejemplo, es posible que la optimización en este caso no se elimine ni cambie algo que "haga un error", sino que divide su disco duro en trozos y paraleliendo el esfuerzo.

De cualquier manera, primero, perfil de la ejecución e identifique los peores delincuentes.

 

Can you please look into my code and suggest me some performance improvement techniques.

No -- it doesn't work like that. While there are some obvious things you may catch visually (like observing string comparisons at each iteration) every time you optimize you should start by profiling your execution, then isolating the parts that take the most time, then optimizing, then profiling again.

For example, it's possible that optimizing in this case is not removing or changing something you "do wrong" but splitting your hard drive into chunks and parallelizing the effort.

Either way, first, profile the execution and identify the worst offenders.

 
 
   
   
6
 
vote

No muestra el código para "compilar la respuesta en un archivo binario", así que no podemos revisar eso. ¿Su prueba muestra que solo el código que se muestra en la OP, sin la salida, es lento? Revisando el código que mostró ...


No sé una API de Windows más rápida que FindFirstFileW/FindFirstNextW : My Googling no encontró una versión asíncrona de estas API. Sin embargo:

  • Alguien sugirió que IShellFolder::EnumObjects podría ser más rápido .
  • Alguien más sugirió que FSCTL_ENUM_USN_DATA puede ser más rápido - y DeviceiOControl () es opcionalmente una API asíncrona, por lo que puede emitir varios de ellos al mismo tiempo (que podrían ser más rápido)

Esto es innecesario (está copiando el nombre de archivo en la memoria asignada por el montón) ...

  FileName = FileInfoData->cFileName;   

... ¿Por qué no usar directamente el valor de la cadena Cfilename de estilo C directamente? Reutilizar la memoria que ya existe es probablemente más rápido que cualquier cosa que asigna nuevos tampones de memoria.


Esto podría ser un poco más rápido ...

  if (! (FileName == L"." || FileName == L".."))   

... porque actualmente está haciendo dos comparaciones de cuerdas integrales; Usted podría usar algo como este en su lugar ...

  if ((FileInfoData->cFileName[0] != L`.`)     ? true // doesn't start with '.'     : (FileInfoData->cFileName[1] == 0)     ? false // is "."     : (FileInfoData->cFileName[1] != L`.`)     ? true // doesn't start with ".."     : (FileInfoData->cFileName[2] != 0) // is not ".."     )   

Por lo general, prefiero la referencia de paso en lugar de copiar el valor, el valor, para cualquier tipo de clase; así que en lugar de ...

  EnumFiles(CString FolderPath, CString SearchParameter,WIN32_FIND_DATAW *FileInfoData) {...}   

... esto en lugar ...

  EnumFiles(const CString& FolderPath, const CString& SearchParameter,     WIN32_FIND_DATAW *FileInfoData) {...}   
La

es probable que el valor por valor esté copiando valores de cadena de un objeto a otro, o al menos que se ejecute el código para compartir el valor entre dos objetos.

Alternativamente, todas las instancias (recursivas) de la función enumfiles podrían compartir un 9988777665544337 usado para FolderPath y para 9988777665544339 y pasamos entre el Las instancias de funciones de enumfiles recursivos como un puntero no-const IShellFolder::EnumObjects0 o como una variable privada estática. Eso evitaría hacer una operación de montón (por ejemplo, IShellFolder::EnumObjects1 ) para cada nuevo nombre de archivo.

 

You don't show the code to "compile the response in a binary file" so we can't review that. Does your testing show that only the code shown in the OP, without the output, is slow? Reviewing the code you showed ...


I don't know a faster Windows API than FindFirstFileW/FindFirstNextW: my Googling found no asynchronous version of these APIs. However:

  • Someone suggested that IShellFolder::EnumObjects might be faster.
  • Someone else suggested that DeviceIoControl() with FSCTL_ENUM_USN_DATA might be faster -- and DeviceIoControl() is optionally an asynchronous API, so you can issue several of them at the same time (which might be faster)

This is unnecessary (you're copying the filename into heap-allocated memory) ...

FileName = FileInfoData->cFileName; 

... why not use the C-style cFileName string value directly? Reusing memory which already exists is probably faster than anything which allocates new memory buffers.


This could be slightly faster ...

if (! (FileName == L"." || FileName == L"..")) 

... because it's currently doing two whole-string comparisons; you could use something like this instead ...

if ((FileInfoData->cFileName[0] != L`.`)     ? true // doesn't start with '.'     : (FileInfoData->cFileName[1] == 0)     ? false // is "."     : (FileInfoData->cFileName[1] != L`.`)     ? true // doesn't start with ".."     : (FileInfoData->cFileName[2] != 0) // is not ".."     ) 

I usually prefer pass-by-reference instead of pass-by-copying-the-value, for any type of class; so instead of ...

EnumFiles(CString FolderPath, CString SearchParameter,WIN32_FIND_DATAW *FileInfoData) {...} 

... this instead ...

EnumFiles(const CString& FolderPath, const CString& SearchParameter,     WIN32_FIND_DATAW *FileInfoData) {...} 

Pass-by-value is likely to be copying string values from one object to another, or at least running code to share the value between two objects.

Alternatively, all (recursive) instances of the EnumFiles function could share a WCHAR filenameBuffer[MAX_FILENAME_LEN] used for FolderPath and for FolderPath + FileName +(L"\\"), and passed between the recursive EnumFiles function instances as a non-const WCHAR* pointer or as a static private variable. That would avoid doing a heap operation (e.g. malloc) for each new filename.

 
 
   
   

Relacionados problema

4  Juego de serpiente básica en c  ( Basic snake game in c ) 
Quería aprender C y Win32, así que pensé que la mejor manera de empezar sería crear un juego simple para familiarizarse con el idioma, así que hice la serpien...

3  std :: string / std :: wtring plantilla wrapper para Win32 API  ( Stdstring stdwstring template wrapper for win32 api ) 
No he completado esto, pero quiero hacer mi propia biblioteca de plantillas para envolver la API de Win32 para que sea compatible con STD :: STRING / STD :: W...

2  Creación de una identificación única para una aplicación en tiempo de ejecución  ( Creating a unique id for an application on runtime ) 
Esto parece funcionar en alguna versión de Windows y actúa raro en otros. Esto es inestable y redundante. ¿Cómo puedo mejorar esto de una manera que tiene e...

7  Pruebas si el nodo de TreeView está marcado  ( Testing if treeviews node is checked ) 
He respondido recientemente a una Pregunta en el desbordamiento de la pila ¿Dónde que OP quería determinar programáticamente si el nodo remaining_distance0...

4  Clase de envoltura de creación de ventanas  ( Window creation wrapper class ) 
Esta pregunta ahora tiene un seguimiento aquí No creo que haya ninguna técnica nueva en mi código, pero en mi opinión está bien, todo en todos (con un poc...

4  Recreated la funcionalidad de consulta de la consola de la consola de Microsoft en C ++ (reg.exe)  ( Recreated microsofts console registry tools query functionality in c reg ex ) 
Decidí intentar recrear la funcionalidad de consulta reg.exe de Microsoft. "Reg.exe" es la herramienta de registro de consola de Microsoft. Utilicé la docum...

6  Código Winapi para consultas DNS  ( Winapi code for dns queries ) 
Este es solo un código de prueba que estoy haciendo para aprender C ++ 11. Recopila y corre constantemente. Pero, ¿es algo malo que eventualmente (o bajo circ...

2  sistema de archivos crea una carpeta  ( Filesystem create a folder ) 
Tengo una mezcla de dos idiomas C y C ++ El código encuentra la carpeta Mis documentos y crea carpetas adicionales cuando comienza el programa, no encontré ...

2  Gestión de la memoria para obtener una lista de letras de unidad en Windows  ( Memory management for fetching a list of drive letters on windows ) 
Estoy usando el winapi GetLogicalDriveStrings() Función que requiere un LPWSTR y me pregunto si hay una forma más segura de hacer esto para asegurarse d...

4  Lifesaver: Oculta y manipula Windows  ( Lifesaver hides and manipulates windows ) 
[Esta aplicación está ahora en github !! ] Este es un pequeño programa que escribí para ocultar / mostrar diferentes ventanas en mi PC con Windows. Esto...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos