Tengo una carpeta que tiene más de 250 archivos de 2 GB cada uno. Necesito buscar una cadena/patrón en esos archivos y generar el resultado en un output
expediente. ¡Sé que puedo ejecutar el siguiente comando, pero es demasiado lento!
grep mypattern * > output
Quiero acelerarlo. Como programador en Java, sé que se pueden usar subprocesos múltiples para acelerar el proceso. No sé cómo iniciar grep
en "modo de subprocesos múltiples" y escriba la salida en una sola output
archivo.
Respuesta aceptada:
Hay dos soluciones fáciles para esto. Básicamente, usando xargs
o parallel
.
Enfoque xargs:
Puedes usar xargs
con find
de la siguiente manera:
find . -type f -print0 | xargs -0 -P number_of_processes grep mypattern > output
Donde reemplazará number_of_processes
por la cantidad máxima de procesos que desea que se inicien.
Sin embargo, no se garantiza que esto le brinde un rendimiento significativo en caso de que su rendimiento sea de E/S limitado. En cuyo caso, podría intentar iniciar más procesos para compensar el tiempo perdido esperando E/S.
Además, con la inclusión de buscar, puede especificar opciones más avanzadas en lugar de solo patrones de archivo, como tiempo de modificación, etc...
Un posible problema con este enfoque, como se explica en los comentarios de Stéphane, si hay pocos archivos, xargs
puede no iniciar suficientes procesos para ellos. Una solución será usar -n
opción para xargs
para especificar cuántos argumentos debe tomar de la canalización a la vez. Configuración -n1
forzará xargs
para iniciar un nuevo proceso para cada archivo individual. Este podría ser un comportamiento deseado si los archivos son muy grandes (como en el caso de esta pregunta) y hay una cantidad relativamente pequeña de archivos. Sin embargo, si los archivos en sí son pequeños, la sobrecarga de iniciar un nuevo proceso puede socavar la ventaja del paralelismo, en cuyo caso un mayor -n
el valor será mejor. Por lo tanto, el -n
la opción puede ajustarse de acuerdo con el tamaño y el número de archivos.
Enfoque paralelo:
Otra forma de hacerlo es usar la herramienta Ole Tange GNU Parallel parallel
, (disponible aquí). Esto ofrece un mayor control de grano fino sobre el paralelismo e incluso se puede distribuir entre múltiples hosts (sería beneficioso si su directorio es compartido, por ejemplo).
La sintaxis más simple usando paralelo será:
find . -type f | parallel -j+1 grep mypattern
donde la opción -j+1
indica a paralelo que inicie un proceso por encima de la cantidad de núcleos en su máquina (esto puede ser útil para tareas limitadas de E/S, incluso puede intentar aumentar la cantidad).
Parallel también tiene la ventaja sobre xargs
de retener realmente el orden de la salida de cada proceso y generar una salida contigua. Por ejemplo, con xargs
, si el proceso 1 genera una línea, diga p1L1
, el proceso 2 genera una línea p2L1
, el proceso 1 genera otra línea p1L2
, la salida será:
p1L1
p2L1
p1L2
mientras que con parallel
la salida debe ser:
p1L1
p1L2
p2L1
Esto suele ser más útil que xargs
salida.