Necesita sugerencias de expertos en la siguiente comparación:
Segmento de código usando el bucle:
for file in `cat large_file_list`
do
gzip -d $file
done
Segmento de código con expansión simple:
gzip -d `cat large_file_list`
¿Cuál será más rápido? Tiene que manipular grandes conjuntos de datos.
linux
bash
shell-script
shell
León
fuente
fuente
gzip
en su sistema, el número de archivos en la lista de archivos y el tamaño de esos archivos.xargs gzip -d < large_file_list
pero tenga cuidado con los espacios en los nombres de archivo, tal vez contr \\n \\0 large_file_list | xargs -0 gzip -d
Respuestas:
Complicaciones
Lo siguiente solo funcionará algunas veces:
Hay tres problemas (en
bash
y la mayoría de los otros depósitos tipo Bourne):Fallará si algún nombre de archivo tiene una pestaña de espacio o caracteres de nueva línea (suponiendo que
$IFS
no se haya modificado). Esto se debe a la división de palabras del shell .También es probable que falle si algún nombre de archivo tiene caracteres glob-active. Esto se debe a que el shell aplicará la expansión del nombre de ruta a la lista de archivos.
También fallará si los nombres de archivo comienzan con
-
(siPOSIXLY_CORRECT=1
eso solo se aplica al primer archivo) o si algún nombre de archivo es-
.También fallará si hay demasiados nombres de archivo en él para caber en una línea de comando.
El código siguiente está sujeto a los mismos problemas que el código anterior (excepto el cuarto)
Solución confiable
Si
large_file_list
tiene exactamente un nombre de archivo por línea, y un archivo llamado-
no está entre ellos, y está en un sistema GNU, entonces use:-d'\n'
le dicexargs
que trate cada línea de entrada como un nombre de archivo separado.-r
le dice quexargs
no ejecute el comando si el archivo de entrada está vacío.--
dicegzip
que los siguientes argumentos no deben tratarse como opciones, incluso si comienzan con-
.-
sin embargo, solo se trataría como en-
lugar del archivo llamado-
.xargs
pondrá muchos nombres de archivo en cada línea de comando pero no tantos que excedan el límite de la línea de comando. Esto reduce el número de veces quegzip
se debe iniciar un proceso y, por lo tanto, lo hace más rápido. También es seguro: los nombres de los archivos también estarán protegidos contra la división de palabras y la expansión del nombre de ruta .fuente
for
bucle será, con diferencia, el más lento. Los otros dos métodos tendrán una velocidad muy cercana entre sí.xargs
: al menos la versión GNU tiene la--arg-file
opción (forma corta-a
). Entonces uno podría hacer en suxargs -a large_file_list -rd'\n' gzip -d
lugar. Efectivamente, no hay diferencia, aparte del hecho de que<
es un operador de shell yxargs
leería desde stdin (que shell "enlaza" al archivo), mientras-a
quexargs
abriría explícitamente el archivo en cuestiónparallel
para ejecutar múltiples copias degzip
, peroxargs
(al menos el GNU), también tiene el-P
interruptor para eso. En máquinas multinúcleo que pueden marcar la diferencia. Pero también es posible que la descompresión esté completamente unida a E / S de todos modos.Dudo que importe mucho.
Usaría un bucle, solo porque no sé cuántos archivos están listados en el archivo de lista, y no sé (generalmente) si alguno de los nombres de archivo tiene espacios en sus nombres. Hacer una sustitución de comando que generaría una lista muy larga de argumentos puede dar como resultado un error "Lista de argumentos demasiado larga" cuando la longitud de la lista generada es demasiado larga.
Mi bucle se vería así
Esto también me permitiría insertar comandos para procesar los datos después del
gunzip
comando. De hecho, dependiendo de lo que realmente sean los datos y de lo que se necesita hacer con ellos, incluso puede ser posible procesarlos sin guardarlos en el archivo:(donde
process_data
hay alguna canalización que lee los datos sin comprimir de la entrada estándar)Si el procesamiento de los datos lleva más tiempo que descomprimirlos, la cuestión de si un bucle es más eficiente o no se vuelve irrelevante.
Idealmente , preferiría no trabajar en una lista de nombres de archivo, y en su lugar usar un patrón global de nombre de archivo, como en
donde
./*.gz
hay algún patrón que coincida con los archivos relevantes. De esta manera, no dependemos del número de archivos ni de los caracteres utilizados en los nombres de archivo (pueden contener líneas nuevas u otros caracteres de espacio en blanco, o comenzar con guiones, etc.)Relacionado:
fuente
De esos dos,
gzip
es probable que el que tiene todos los archivos pasados a una sola invocación sea más rápido, exactamente porque solo necesita iniciarlogzip
una vez. (Es decir, si el comando funciona, vea las otras respuestas para las advertencias).Pero me gustaría recordar la regla de oro de la optimización : no lo haga prematuramente.
No optimices ese tipo de cosas antes de saber que es un problema.
¿Esta parte del programa lleva mucho tiempo? Bueno, descomprimir archivos grandes podría, y tendrás que hacerlo de todos modos, por lo que podría no ser tan fácil de responder.
Medida. Realmente, es la mejor manera de estar seguro.
Verá los resultados con sus propios ojos (o con su propio cronómetro), y se aplicarán a su situación que las respuestas aleatorias en Internet podrían no tener. Pon ambas variantes en scripts y ejecuta
time script1.sh
, ytime script2.sh
. (Haga eso con una lista de archivos comprimidos vacíos para medir la cantidad absoluta de los gastos generales).fuente
¿Qué tan rápido es tu disco?
Esto debería usar todas tus CPU:
Por lo tanto, es probable que su límite sea la velocidad de su disco.
Puedes intentar ajustarte con
-j
:Esto ejecutará la mitad de los trabajos en paralelo como el comando anterior, y estresará menos su disco, por lo que, dependiendo de su disco, esto puede ser más rápido.
fuente