Actualmente uso md5_file()
para ejecutar aproximadamente 15 URL y verificar sus valores hash MD5. ¿Hay alguna manera de que pueda hacer esto más rápido? Tarda demasiado tiempo en recorrerlos a todos.¿Una forma de hacer que md5_file() sea más rápido?
Respuesta
Probablemente lo hagas secuencialmente en este momento. Es decir. buscar datos 1, procesar datos 1, buscar datos 2, procesar datos 2, ... y el cuello de botella puede ser la transferencia de datos.
Puede usar curl_multi_exec() para paralelizar eso un poco. O bien registre un CURLOPT_WRITEFUNCTION y procese cada fragmento de datos (complicado ya que md5() funciona exactamente en un fragmento de datos).
O compruebe que los tiradores curl ya estén terminados y luego procese los datos de ese identificador.
edición: rápida & ejemplo sucia utilizando el hash extension (que proporciona funciones de hash incrementales) y un php5.3+ closure:
$urls = array(
'http://stackoverflow.com/',
'http://sstatic.net/so/img/logo.png',
'http://www.gravatar.com/avatar/212151980ba7123c314251b185608b1d?s=128&d=identicon&r=PG',
'http://de.php.net/images/php.gif'
);
$data = array();
$fnWrite = function($ch, $chunk) use(&$data) {
foreach($data as $d) {
if ($ch===$d['curlrc']) {
hash_update($d['hashrc'], $chunk);
}
}
};
$mh = curl_multi_init();
foreach($urls as $u) {
$current = curl_init();
curl_setopt($current, CURLOPT_URL, $u);
curl_setopt($current, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($current, CURLOPT_HEADER, 0);
curl_setopt($current, CURLOPT_WRITEFUNCTION, $fnWrite);
curl_multi_add_handle($mh, $current);
$hash = hash_init('md5');
$data[] = array('url'=>$u, 'curlrc'=>$current, 'hashrc'=>$hash);
}
$active = null;
//execute the handles
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
foreach($data as $d) {
curl_multi_remove_handle($mh, $d['curlrc']);
echo $d['url'], ': ', hash_final($d['hashrc'], false), "\n";
}
curl_multi_close($mh);
(no se han comprobado los resultados aunque ... es sólo un punto de partida)
+1. Paralelizar descargas es probable que sea una gran victoria aquí. También podría paralelizar la porción md5, ya sea usando el comando CLI 'md5sum' (ej.' Exec ('bash -c' md5sum file1> file1.md5 & "')'), o usando algo como PHP's pcntl_fork() para bifurcar múltiples llamadas a md5_sum(). Ambos tienen sus inconvenientes, pero en el contexto correcto, pueden ser lo mejor que se puede hacer. –
Y debo admitir que ni siquiera he probado si la descarga realmente continúa mientras se ejecuta la devolución de llamada. Pero dado que las porciones de datos son supuestamente pequeñas, espero que no importe (mucho). – VolkerK
El algoritmo md5 es casi tan rápido como puede obtenerse, y recuperar URL es casi tan rápido como puede (lento si los archivos son grandes o tiene una conexión lenta). Entonces no No puedes hacerlo más rápido.
Bueno, obviamente no se puede hacer nada con md5_file()
para hacer más rápido, sin embargo, se puede utilizar un poco de micro-optimizations o código re-factoring para obtener alguna ganancia de velocidad, pero de nuevo no se puede acelerar la función incorporada md5_file()
.
... Claro, algunas micro-optimizaciones podrían reducir 2 milisegundos de su tiempo de ejecución. Tal vez. O podría simplemente arrastrar las URL en paralelo y ahorrar unos segundos. Las "micro optimizaciones" casi nunca valen la pena. –
@Frank, esto se publicó antes de que la pregunta se editara para incluir realmente el código en cuestión (que, hasta que se agregó el código, básicamente se le preguntó cómo acelerar md5_file()). –
No. Dado que se trata de una función incorporada, no hay forma de hacerlo más rápido.
Pero si su código está descargando archivos antes de MD5ing, es posible que sus descargas sean más rápidas. También puede ver un pequeño aumento de velocidad configurando el tamaño del archivo (usando ftruncate) antes de escribirlo si conoce el tamaño antes de tiempo.
Además, si los archivos son lo suficientemente pequeños como para guardarlos en la memoria y ya los tiene en la memoria (porque han sido descargados o están siendo leídos para otro propósito) entonces puede usar md5
para operarlos en la memoria en lugar de md5_file
que requiere que se lea de nuevo desde el disco.
¿Presumiblemente está revisando las mismas URL durante un período de tiempo? ¿Podría verificar los últimos encabezados modificados para la URL? Si la página que se está verificando no ha cambiado, entonces no habría necesidad de volver a calcular el MD5.
También podría solicitar las páginas de forma asíncrona para que puedan procesarse en paralelo, en lugar de en serie, lo que debería acelerarlo.
La velocidad del algoritmo MD5 es lineal. Mientras más grande sea la entrada, más tiempo tomará, así que si el archivo es grande, realmente no hay mucho que puedas hacer.
Ahora, como VolkerK ya sugirió, el problema probablemente no es el hash md5 sino la recuperación y lectura del archivo en la red.
Veo una muy buena sugerencia de optimizar here. Esto funcionará bien especialmente para archivos grandes, donde md5_file está leyendo el archivo y esta función solo compara el segundo byte de cada archivo.
Explicar lo que quiere hacer ayudaría. En caso de que quiera verificar un archivo con sus valores hash MD5:
No es un método seguro ya que es propenso a Collision attack. Debería usar hashes múltiples (quizás dividiendo el archivo) o usar otros métodos hash.
- 1. ¿Cómo hacer que este script sed sea más rápido?
- 2. ¿Cómo hacer que este Twisted Python Proxy sea más rápido?
- 3. Cómo hacer que mi código sea rápido
- 4. ¿Cómo hacer que JVM arranque más rápido?
- 5. ¿Cómo hacer que doxygen funcione más rápido?
- 6. ¿Qué puede hacer que el código F # no optimizado sea más rápido que el código optimizado?
- 7. Hacer que JAXB vaya más rápido
- 8. Cómo hacer que TimePicker sea más pequeño
- 9. ¿Puedo hacer que JUnit sea más detallado?
- 10. ¿Cómo hacer que Rotate3dAnimation sea más suave?
- 11. Cómo hacer que el tiempo de espera de SqlConnection sea más rápido
- 12. La forma más eficiente de hacer que una estructura de datos sea segura (Java)
- 13. ¿Cómo hacer que el proceso de escaneo de puertos TCP sea más rápido?
- 14. ¿La forma más rápida de hacer que el sitio web sea receptivo?
- 15. ¿Qué cosas pueden hacer que el desarrollo de CSS sea más rápido?
- 16. ¿Qué hace que STL sea rápido?
- 17. ¿Cómo puedo hacer que mostrar imágenes en WPF sea más "rápido"?
- 18. ¿Cómo puedo hacer que mi caché. LRU simple sea más rápido?
- 19. Hacer que una lista enlazada sea segura
- 20. ¿Cómo hacer que EditText sea más pequeño que el predeterminado?
- 21. Cómo hacer que el eclipse IDE se construya más rápido
- 22. Algo más rápido que HttpHandlers?
- 23. Más rápido que String.Replace()
- 24. ¿Cómo puedo hacer que Quartus II compile más rápido?
- 25. ¿Puedo hacer que maven-assembly-plugin vaya más rápido?
- 26. Algo más rápido que get_headers()
- 27. ¿Es + = más rápido que - =?
- 28. Cómo hacer que el emulador de Android arranque más rápido
- 29. Cómo hacer que la declaración if grande sea más legible
- 30. ¿Cómo hacer que un sitio web funcione más rápido?
"ejecutar a través de aproximadamente 15 URL" significa algo así como 'md5_file ('http: //some.url/foo')' en un bucle con 15 URL diferentes? ¿Qué tan grandes son esos "archivos"? – VolkerK
Sí, eso es exactamente. Los extraigo de una base de datos MySQL y luego los ejecuto en md5_file ($ result) en un bucle. Los archivos son MUY pequeños, y de hecho no tienen salida de visualización, no tienen interfaz de usuario, solo una página en blanco cuando se ven – Rob
El problema es que estás calculando los hashes en secuencia en lugar de en paralelo; 'md5_file' no es el cuello de botella. Además, seguramente el hash de un archivo vacío siempre será el mismo. – salathe