Déjame dar un ejemplo:
$ timeout 1 yes "GNU" > file1
$ wc -l file1
11504640 file1
$ for ((sec0=`date +%S`;sec<=$(($sec0+5));sec=`date +%S`)); do echo "GNU" >> file2; done
$ wc -l file2
1953 file2
Aquí puede ver que el comando yes
escribe 11504640
líneas en un segundo, mientras que solo puedo escribir 1953
líneas en 5 segundos usando bash for
y echo
.
Como se sugiere en los comentarios, hay varios trucos para hacerlo más eficiente, pero ninguno se acerca a la velocidad de yes
:
$ ( while :; do echo "GNU" >> file3; done) & pid=$! ; sleep 1 ; kill $pid
[1] 3054
$ wc -l file3
19596 file3
$ timeout 1 bash -c 'while true; do echo "GNU" >> file4; done'
$ wc -l file4
18912 file4
Estos pueden escribir hasta 20 mil líneas en un segundo. Y se pueden mejorar aún más para:
$ timeout 1 bash -c 'while true; do echo "GNU"; done >> file5'
$ wc -l file5
34517 file5
$ ( while :; do echo "GNU"; done >> file6 ) & pid=$! ; sleep 1 ; kill $pid
[1] 5690
$ wc -l file6
40961 file6
Estos nos llevan hasta 40 mil líneas en un segundo. Mejor, ¡pero aún está muy lejos de yes
poder escribir alrededor de 11 millones de líneas en un segundo!
Entonces, ¿cómo se yes
escribe en el archivo tan rápido?
date
es algo pesado, además el shell tiene que volver a abrir la secuencia de salida echo
para cada iteración del bucle. En el primer ejemplo, solo hay una invocación de comando único con una única redirección de salida, y el comando es extremadamente ligero. Los dos no son de ninguna manera comparables.
date
puede ser pesado, vea la edición de mi pregunta.
timeout 1 $(while true; do echo "GNU">>file2; done;)
es la forma incorrecta de usar timeout
ya que el timeout
comando solo comenzará una vez que finalice la sustitución del comando. Utilizar timeout 1 sh -c 'while true; do echo "GNU">>file2; done'
.
write(2)
llamadas del sistema, no a las cargas de otros syscalls, la sobrecarga de shell o incluso la creación de procesos en su primer ejemplo (que se ejecuta y espera date
cada línea impresa en el archivo). Un segundo de escritura es apenas suficiente para que se produzca un cuello de botella en la E / S de disco (en lugar de CPU / memoria), en un sistema moderno con mucha RAM. Si se le permite correr más tiempo, la diferencia sería menor. (Dependiendo de cuán mala sea la implementación de bash que use y la velocidad relativa de la CPU y el disco, es posible que ni siquiera sature la E / S del disco con bash).