2009-10-07 14 views
6

necesito transferir archivos de gran tamaño a través de la red y necesito crear una suma de comprobación para cada hora. entonces la velocidad para generar checksum es crítica para mí.la forma más rápida de crear una suma de comprobación para archivos de gran tamaño en python

de alguna manera no puedo hacer que zlib.crc32 y zlib.adler32 trabajen con archivos de más de 4 GB en la máquina con Windows XP Pro 64bit. ¿Sospecho que he llegado a la limitación de 32 bits aquí? usando hashlib.md5 podría obtener un resultado, pero el problema es la velocidad. toma aproximadamente 5 minutos generar un md5 para un archivo de 4.8 GB. el administrador de tareas muestra que el proceso está usando solo un núcleo.

mis preguntas son:

  1. hay una manera de hacer las obras de CRC en el archivo de gran tamaño? Prefiero usar crc que md5
  2. si no, ¿hay alguna manera de acelerar el md5.hexdigest()/md5.digest? o en este caso, cualquier hashlib hexdigest/digest? ¿Tal vez dividiéndolo en un proceso de múltiples hilos? ¿Cómo puedo hacer eso?

PD: Estoy trabajando en algo similar a un sistema de "Gestión de activos", algo así como svn pero el activo consiste en grandes archivos de imagen comprimida. los archivos tienen pequeños cambios incrementales. el hash/checksum es necesario para detectar cambios y detectar errores.

+0

¿Hay alguna razón por la que no pueda usar rsync? –

+0

¿Necesita verificar su integridad (con el algoritmo apropiado que es la pregunta real) solo porque transfiere los archivos a través de la red? Si es así, esto ya está verificado en el nivel de hardware para los marcos y en la capa Tcp para cualquier parte faltante (supongo que aquí hay una conexión Tcp). Lo siento si eso suena obvio, pero prefiero preguntar. – RedGlyph

+0

hola chicos, gracias por la respuesta.Por qué no puedo usar rsync porque es casi como un sistema de administración de activos que transfiere grandes archivos de imágenes comprimidas. varias personas trabajando en algunos archivos. esos archivos tienen pequeños cambios incrementales que deben ser detectados. por lo tanto, estoy tratando de usar checksum/hash. – pixelblender

Respuesta

0

No es posible utilizar más de un núcleo para calcular el hash MD5 de un archivo grande debido a la naturaleza misma de MD5: espera que un mensaje se divida en fragmentos y se transfiera a la función de hash en estricta secuencia. Sin embargo, puede usar un hilo para leer un archivo en la cola interna, y luego calcular el hash en un hilo separado para que así sea. No obstante, no creo que esto te brinde un impulso significativo en el rendimiento.

El hecho de que lleve tanto tiempo procesar un archivo grande puede deberse a lecturas "sin búfer". Intente leer, digamos, 16 Kb a la vez y luego alimentar el contenido en trozos a la función hash.

+0

gracias por la respuesta Anton. utilizo f.read (1048576) y actualizo haslib.md5() para cada lectura. sí, supongo que crear otro hilo para calcular el hash no dará mucho de impulso de rendimiento – pixelblender

0

md5 no se puede ejecutar en paralelo. Sin embargo, puede md5 el archivo en secciones (en paralelo) y tomar un md5 de la lista de hashes.

Sin embargo, eso supone que el hash no está limitado por IO, lo que sospecho que es. Como sugiere Anton Gogolev, asegúrese de leer el archivo de manera eficiente (en grandes fragmentos de potencia de 2). Una vez que hayas hecho eso, asegúrate de que el archivo no esté fragmentado.

También se debe seleccionar un hash como sha256 en lugar de md5 para los proyectos nuevos.

¿Las sumas de comprobación de zlib son mucho más rápidas que md5 para archivos de 4 Gb?

+0

SHA256 sería mucho más lento que MD5, y no hay necesidad de hacerlo. Sí, ha habido un ataque exitoso para diseñar colisiones con MD5, pero esta aplicación no intenta ser criptográficamente segura. Está usando el hash como una optimización para evitar copias innecesarias. –

+0

gracias por la respuesta Douglas. Creo que sha256 es demasiado para mí y la colisión no es realmente una preocupación para mí. – pixelblender

4

¡Es un problema de selección de algoritmo, en lugar de un problema de selección de biblioteca/idioma!

Parece que hay dos puntos a tener en cuenta sobre todo:

  • cuánto sería el disco E/S afectar el rendimiento global?
  • ¿cuál es la confiabilidad esperada de de la función de detección de errores?

Al parecer, la respuesta a la segunda pregunta es algo así como 'algunos falsos negativos permitió' ya que la fiabilidad de cualquier 32 bits de hachís, en relación con un mensaje de 4 Gb, incluso en un canal moderadamente ruidoso, se no va a ser virtualmente absoluto.

Suponiendo que las E/S se pueden mejorar a través de subprocesos múltiples, podemos elegir un hash que no requiera un escaneo secuencial del mensaje completo. En su lugar, tal vez podamos trabajar el archivo en paralelo, mezclando secciones individuales y combinando los valores hash o agregándolos, para formar un dispositivo de detección de errores más largo y más confiable.

El siguiente paso podría ser formalizar este manejo de archivos como secciones ordenadas, y transmitirlos como tales (para volver a pegarlos al final del destinatario). Este enfoque, junto con información adicional sobre la forma en que se producen los archivos (por ejemplo, pueden ser modificados exclusivamente por anexos, como archivos de registro), incluso puede permitir limitar la cantidad de cálculo de hash requerido. La complejidad adicional de este enfoque debe ponderarse en contra del deseo de tener un cálculo de CRC rápido y rápido.

Nota al margen: Alder32 es no limitado a los tamaños de mensaje por debajo de un umbral determinado. Puede ser solo un límite de la API zlib. (Por cierto, la referencia que encontré sobre zlib.adler32 utilizó un búfer, y bueno ... este enfoque debe evitarse en el contexto de nuestros enormes mensajes, a favor de los procesos transmitidos: leer un poco del archivo, calcular, repetir. .)

+0

hola mjv, gracias por su respuesta. así que supongo que debería crear checksum en varias partes del archivo y combinarlas? – pixelblender

+0

@pixelblender Sí, siempre que las E/S no sean un cuello de botella, una implementación de subprocesos múltiples que procesaría decir "segmentos" de 100 Mb de bytes del archivo, en forma paralela puede esperarse que sea más rápida en general que un enfoque de un solo subproceso . Necesitarás experimentar para determinar la cantidad óptima de hilos (siempre llega un punto en el que agregar hilo no mejora el rendimiento). La lista ordenada de CRC de las "divisiones" individuales de la lata puede ser CRC-ed o, preferiblemente, los CRC se pueden agregar para formar una clave más larga, ofreciendo una mejor detección de errores. – mjv

2

En primer lugar, no hay nada inherente en ninguno de los algoritmos CRC que les impida trabajar en una longitud de datos arbitraria (sin embargo, una implementación particular podría imponer un límite).

Sin embargo, en una aplicación de sincronización de archivos, eso probablemente no importe, ya que es posible que no desee comprimir el archivo completo cuando se vuelve grande, simplemente corta de todos modos. Si hash todo el archivo, y los valores hash en cada extremo difieren, tienes que copiar el archivo completo. Si hash trozos de tamaño fijo, solo tienes que copiar los trozos cuyo hash ha cambiado. Si la mayoría de los cambios en los archivos están localizados (por ejemplo, en la base de datos), es probable que esto requiera mucha menos copia (y es más fácil distribuirlos por cálculos de fragmentos en varios núcleos).

En cuanto al algoritmo hash en sí mismo, la compensación básica es la velocidad frente a la falta de colisiones (dos fragmentos de datos diferentes que producen el mismo hash). CRC-32 es rápido, pero con solo 2^32 valores únicos, se pueden ver colisiones. MD5 es mucho más lento, pero tiene 2^128 valores únicos, por lo que las colisiones casi nunca se verán (pero todavía son teóricamente posibles). Los valores hash más grandes (SHA1, SHA256, ...) tienen aún más valores únicos, pero son más lentos aún: dudo que los necesites: te preocupan las colisiones accidentales, a diferencia de las aplicaciones de firma digital, donde te preocupa deliberadamente (malicuamente) colisiones diseñadas.

Parece que está intentando hacer algo muy similar a lo que hace la utilidad rsync. ¿Puedes usar rsync?

+0

Hola Stephen, gracias por su respuesta. sí, las colisiones no son una preocupación para mí, es por eso que prefiero usar crc32. He editado mi publicación con respecto a lo que estoy tratando de lograr con suma de comprobación. – pixelblender

+0

Incluso si no puede encontrar una implementación adecuada de Python del algoritmo CRC32, debería ser capaz de adaptar una implementación publicada en cualquier idioma. Incluso podría aprovechar las capacidades de Python para vincular a bibliotecas de códigos nativos. Esto incluso podría ayudar a la velocidad (pero su rendimiento probablemente esté limitado por E/S de disco de todos modos con CRC-32). Los algoritmos CRC son bastante simples. Implementé CRC-8 y CRC-16 en unas pocas líneas de C y una tabla de datos estáticos. No recuerdo haber implementado CRC-32, pero estoy bastante seguro de que no es mucho más complicado. –

1

Es posible que esté alcanzando un límite de tamaño para archivos en XP. El de 64 bits le brinda más espacio de direcciones (eliminando el espacio de direcciones de 2GB (más o menos) por aplicación), pero probablemente no haga nada para el problema del tamaño del archivo.

Cuestiones relacionadas