2012-01-16 19 views
8

Estoy frente a un fragmento de código, que copia un archivo en un dispositivo usb. parte siguiente es la importante:Rendimiento de copiar un archivo con fread/fwrite en USB

while((bytesRead = fread(buf, 1, 16*1024, m_hSource)) && !bAbort) { 
    // write to target 
    long bytesWritten = fwrite(buf, 1, bytesRead, m_hTarget); 

    m_lBytesCopied += bytesWritten; 

La cosa, el cliente dijo, que es bastante lento en comparación con PC < normales -> Speed ​​USB. No codifiqué esto, así que es mi trabajo optimizarlo.

Así que me preguntaba, si es un mejor enfoque para leer por primera vez el archivo completo y luego escribir el archivo en un solo paso. Pero no sé cuán propenso a errores sería esto. El código también verifica después de cada copystep si todos los bytes están escritos correctamente, por lo que también pueden ralentizar el proceso.

No soy tan C++ & gurú del hardware, así que les pregunto a ustedes, cómo podría acelerar las cosas y mantener la copia exitosa.

+2

Busque en otra parte el cuello de botella. Puede obtener una pequeña mejora cambiando el tamaño del búfer, pero su problema probablemente sea otra cosa. –

+0

Bueno, esa es la única parte que está haciendo algo con este problema en particular. Entonces puede ser solo el código. –

+0

Quite la marca de que los bytes se escribieron correctamente. Si no puede confiar en la primera escritura, entonces no puede confiar en la siguiente lectura que usa para la verificación. (Supongo que está revisando los bytes escritos para ver si hay errores.) –

Respuesta

3
  1. Probar leer/escribir en gran parte. 16M, 32M no están mal para copiar el archivo.
  2. Si solo quiere copiar el archivo siempre puede invocar system() Será más rápido.
  3. El código también comprueba después de cada copystep si todos los bytes están escritos correctamente, por lo que también pueden ralentizar el proceso.

    Puede comprobarlo creando hash de trozo más grande. Como dividir el archivo en trozos de 64M. Luego haz coincidir los hashes de esos fragmentos. El protocolo Bittorrent tiene esta característica.

  4. Si tiene mmap o MapViewOfFile disponibles, asignar el archivo primero. Luego escríbela a usb. De esta manera, la operación de lectura será manejada por kernel.

  5. Kerrek comenta sobre usar memcpy en mmap. memcpy con 2 mmap ed archivo parece genial.

También tenga en cuenta que, los sistemas operativos más recientes se escriben en la memoria USB cuando se eliminan. Antes de eliminarlo, solo escribe los datos en un caché. Así que copiar desde el sistema operativo puede aparecer más rápido.

+1

# 4 suena bien: memory-map y usa 'memcpy'. –

+0

@KerrekSB +1. 'memcpy' con 2 archivos' mmap'ed parece una gran opción. Actualizado mi pregunta. –

1

¿Qué ocurre con la superposición de lecturas y escrituras?

En el código actual, el tiempo total es time(read original) + time(write copy), si lee el primer bloque, luego al escribirlo comienza a leer el segundo bloque, etc. su tiempo total sería max(time(read original), time(write copy)) (más el tiempo de lectura/escritura del primero y últimos bloques que no se canalizarán).

Podría ser casi la mitad de las veces si leer y escribir lleva más o menos el mismo tiempo.

Puede hacerlo con dos hilos o con IO asincrónico. Desafortunadamente, los hilos y async IO dependen de la plataforma, por lo que deberá consultar el manual de su sistema o elegir las bibliotecas portátiles apropiadas.

+0

AFAIK, USB I/O también depende principalmente de la plataforma, ¿no es así? –

+0

@ AndréCaron Supongo que sí si está compilando un controlador, pero en este caso creo que es solo acceder al sistema de archivos, por lo que puede 'fopen' archivos (y eso es estándar). – fortran

0

Simplemente me gustaría ir con algunas funciones específicas del sistema operativo que de seguro lo hacen más rápido que cualquier cosa escrita solo con funciones c/C++.

Para Linux esto podría ser sendfile función. Para Windows CopyFile hará el trabajo.

Cuestiones relacionadas