Tengo FILE_A que tiene más de 300,000 líneas y FILE_B que tiene más de 30 millones de líneas. Creé un script Bash que agrupa cada línea en FILE_A en FILE_B y escribe el resultado del grep en un nuevo archivo.
Todo este proceso lleva más de 5 horas.
¿Cómo puedo mejorar el rendimiento de mi script?
Estoy usando grep -F -m 1
como el comando grep. FILE_A tiene este aspecto:
123456789
123455321
y FILE_B es así:
123456789,123456789,730025400149993,
123455321,123455321,730025400126097,
Entonces, con Bash tengo un while
bucle que selecciona la siguiente línea en FILE_A y la ajusta en FILE_B. Cuando el patrón se encuentra en FILE_B, lo escribo en el archivo result.txt.
while read -r line; do
grep -F -m1 $line 30MFile
done < 300KFile
algorithms
performance
perl
bash
rogerio_marcio
fuente
fuente
Aquí hay una respuesta de Perl para la posteridad. Rutinariamente hago esto para hacer coincidir líneas de 1M con líneas de 30-35M. Tarda alrededor de 10 segundos en terminar.
Primero, hash up FILE_A:
Luego, si su archivo grande está delimitado y sabe qué columna debe seguir, verifique solo la existencia de la clave hash mientras ejecuta FILE_B, que es mucho, mucho más rápido que verificar la igualdad o la coincidencia de expresiones regulares:
Si su archivo de destino más grande no se puede analizar bien, entonces este script pierde su valor ya que gran parte de su velocidad proviene de no tener que encender el motor de expresión regular .
fuente
Si no le importa una programación más complicada, considere usar árboles de sufijos (o una variante).
Puede preprocesar
FILE_B
usando el algoritmo de Ukkonen en tiempo lineal. Luego, consulta cada línea en elFILE_A
tiempo lineal en la longitud de la línea y obtiene todos los números de línea que coinciden (puede que necesite adaptar el árbol un poco) que puede escribir en un archivo de resultados.Todo el procedimiento se ejecuta en el tiempo O (n + Nm) si n es la longitud de
FILE_B
,N
es el número de líneasFILE_A
y m es la longitud de la línea más largaFILE_A
, esto es esencialmente tiempo de ejecución lineal. Supera el tiempo cuadrático que tu enfoque original necesita por magnitud.fuente
Encontré la
--mmap
bandera últimamente, no tuve la oportunidad de probarla, pero estaré feliz de escuchar sus hallazgos. Aquí está la descripción de la página del manual:Vea esto o esto para obtener más información sobre
mmap
.fuente
--mmap
dosis no arroja nada, recomendaría una carrera con--mmap
y otra sin. Y luego usewc
para ver que tiene la misma cantidad de salida: esta debería ser una prueba sólida teniendo en cuenta que ejecutamos 2 veces grep, y solo difería un indicador.¿por qué no pones ese archivo en una base de datos? Las bases de datos son realmente buenas para hacer una combinación eficiente, hash, unión de bucle anidado como esta. Y son muy buenos para utilizar la memoria virtual.
fuente