Necesita un bucle para dormir por una fracción de segundo

En mi máquina necesito ejecutar un ciclo que itera 1 command simple que debe tener un retraso expresado en fracciones de segundo.

Digamos que necesito:

  • para save un file con un enumaration creciente (file-0, file-1, file-2, …) genere algo trivial para este ejemplo como time > file-$x
  • Necesito hacer esto cada 1/70 de segundo (como ejemplo) porque me gustaría express mi time con fracciones de segundo.

¿Cómo puedo ser realmente preciso y tener todo expresado con un script bash?

La fracción puede generar una cantidad indeterminable, necesito ser preciso y necesito al less 4-5 decimales.

Para convertir de fracciones a decimales en bash, haz algo como

 myvar=$(echo "scale=4; 5/10" | bc) 

Entonces, para hacer un ciclo en ese valor,

 for i in $(seq 1 1000); do sleep $myvar; done 

Mi implementación de suspensión en Debian (GNU) parece aceptar valores de sueño decimales.

Desafortunadamente..

Con ese tipo de precisión (4-5 lugares decimales), vas a querer algo así como un script de Perl o un progtwig comstackdo; La sobrecarga de llamar a cualquier progtwig dentro del ciclo va a agregar mucha inestabilidad. Llamar al sueño en sí tomará unos pocos milisegundos.

Considere lo siguiente, un sueño de 1/10,000 de segundo, hecho 1000 veces:

 time for i in $(seq 1 1000); do sleep 0.0001; done real 0m2.099s user 0m3.080s sys 0m1.464s 

El resultado esperado sería 1/10 de segundo. El sueño no está cerca de las tolerancias que deseas.

https://stackoverflow.com/questions/896904/how-do-i-sleep-for-a-millisecond-in-perl

usando Perl's Time :: HiRes, 1000 * 1000 microsegundos:

 my $i=0; for($i=0;$i<=1000;$i++) { usleep(1000); } real 0m1.133s user 0m0.024s sys 0m0.012s 

nos da mucho más cerca de un segundo.

Engendrar un process y cargar un nuevo ejecutable probablemente demorará unos milisegundos, por lo que ese tipo de precisión realmente no tiene sentido. También tenga en count que el time de CPU en muchos sistemas se asigna a processs por sectores de hasta 10 ms.

Una vez dicho esto, algunas implementaciones de sleep toman fracciones de segundos, y tanto zsh como ksh93 pueden hacer que su variable $SECONDS especial sea fraccional con typeset -F SECONDS .

Ejemplo (zsh):

 $ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do sleep $((1./70)); date +%s.%N; done | { head -n3;echo ..;tail -n3; }; echo $SECONDS 1350076317.374870501 1350076317.391034397 1350076317.407278461 .. 1350076318.464585550 1350076318.480887660 1350076318.497133050 1.1393780000 

Ups, se movió. Puede ajustar el time de sueño basado en $SECONDS :

 $ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do sleep $((i/70. - SECONDS)); date +%s.%N; done | { head -n3;echo ...;tail -n3; }; echo $SECONDS 1350076420.262775654 1350076420.277012997 1350076420.291302750 ../.. 1350076421.219682227 1350076421.234134663 1350076421.248255685 1.0020580000 

Esos 2 milisegundos adicionales probablemente se tendrán en count al ejecutar los últimos commands de sleep y date .

También tenga en count que zsh tiene un zselect incorporado con time de espera expresado en centésimas de segundo. Y ksh93 tiene incorporado el sleep (y acepta puntos flotantes) y su printf puede imprimir date / hora.

 $ typeset -F SECONDS=0; for ((i=1; i<=70; i++)); do ((i<4 || i>67)) && printf '%(%S.%N)T\n' now; sleep $((i/70.-SECONDS)); done; echo $SECONDS 20.823349000 20.837510000 20.851663000 21.780099000 21.794254000 21.808405000 0.9992358685 

Si quiere algo más preciso, probablemente querrá un sistema operativo en time real o un sistema operativo con capacidades en time real y, desde luego, no usará un shell.

Tal vez simplemente puedes correr

 sleep 0.7 

?

 man 1 sleep 

en mi distro archlinux :

DESCRIPCIÓN Pausa durante NUMBER segundos. SUFFIX puede ser 's' por segundos (el valor pnetworkingeterminado), 'm' por minutos, 'h' por horas o 'd' por días. A diferencia de la mayoría de las implementaciones que requieren que NUMBER sea un número integer, aquí NUMBER puede ser un número arbitrario de coma flotante. Con dos o más arguments, pause por la cantidad de time especificada por la sum de sus valores.

Si el modo de sleep su caparazón no acepta fracciones, use perl.

 sleep_fraction() { /usr/bin/perl -e "select(undef, undef, undef, $1)" } sleep_fraction 0.01428 

Si necesita descubrir la fracción, use echo "scale=5; 1/70" | bc echo "scale=5; 1/70" | bc

En Alpine Linux (Busybox) puede recorrer microsegundos con usleep 10 (equivalente a 0.00001 de segundo)

GNU sleep admite fracciones de segundo: sleep 0.00001