Cómo ajustar el command de time para medir el time transcurrido de un progtwig

Estoy tratando de get el time que mi progtwig tarda en terminar (también conocido como time transcurrido), así que estoy usando el time común.

Lo que obtengo al hacer esto son 3 medidas: usuario, sistema y total. Esto está bien, pero descubrí que el time de usuario que me interesa tiene solo dos decimales y necesitaría más. ¿Hay alguna forma de que pueda get más decimales fuera de mi order de time?

Ejemplo: time ./myCProgram
Salida: 0.17s usuario 1.21s sistema 130% cpu 0.187 total

Deseada salida deseada: 0.17000s usuario 1.21s sistema 130% CPU 0.187 total (o más decimales)

Si todo lo que quiere es time transcurrido, entonces con zsh o ksh93:

 $ typeset -F SECONDS=0; sleep 1; print "$SECONDS" 1.0012850761 

Ahora, si ese tipo de precisión tiene sentido es otro asunto.

Tiempo de computación en nanosegundos bajo GNU/Linux , usando bash .

ADVERTENCIA Esta publicación se convirtió en obsoleta mediante un nuevo y agradable método que se discutió allí: Profiling bash (3 respuestas) y con el file fuente bash completo listo para usar : Elap-bash V3

Maneras de recuperar valores confiables

Hay alguna manera de pedir time en una granularidad más fina que un segundo.

Primero, pero no mejor: 1/100 de segundo

Durante 1/100 de segundo, puede simplemente referirse a /proc/uptime :

 sed 's/ .*$//' /proc/uptime 276440.58 

La compensación de time para agregar para calcular la hora UTC real se puede get por uno de:

 ps ho lstart 1 | date -f - +%s 1357193821 

o

 date +%s.%N-$(sed 's/ .*$//' /proc/uptime ) | bc -l 1357193821.088187101 

Como el desplazamiento es estático, este valor podría computarse solo 1 vez, al comienzo del script.

1 / 1000000000th de segundos, usando solo inputs de process:

Para computar con nanosegundos , hay una proc entry , llamada /proc/timer_list que contiene tanto uptime como offset :

 sed < /proc/timer_list -ne '/now at/p;/offset/{p;q}' now at 276350507668586 nsecs .offset: 1357193821075753443 nsecs 

Así que esto

 echo $(($(sed < /proc/timer_list -ne ' /^now at/{s/now at \([0-9]*\) ns.*$/\1/;H}; /offset/{s/^.*: *\([0-9]*\) ns.*$/\1/;G;s/\n\+/+/;p;q}'))) 1357470173543424035 

es el número integer de nanosegundos transcurridos desde 1970-1-1 00:00:00 UTC .

Para calcular un integer bajo bash , no hay necesidad de usar bc y para analizar files de proc, podríamos usar mapfile que es un bash builtin :

 # first, some static variables (with fork, but only 1 time, at begin;): nowAtLine=$(($(sed -ne < /proc/timer_list '/now at/{=;q}')-1)) offset=$(sed -ne < /proc/timer_list ' /offset/{s/^.*: *\([0-9]*\) n.*$/\1/p;q}') # than this will be a lot quicker than a fork: mapfile -n 1 -s $nowAtLine timerList </proc/timer_list && timerList=($timerList) && echo $((${timerList[2]}+offset)) 1357470173543424035 

1 / 1000000000th de segundos, usando la herramienta binaria de date :

Y finalmente, si no existen, podríamos llamar a la date teniendo en count que es un fork que toma mucho más time que leer proc files , permaneciendo en una sola session de bash.

 date +%s%N 1357470074808968375 

Mi function elap.bash

Basado en esto, escribí una function elap bash , con dos contadores: 1 para cada llamada y el otro para un tipo de overall duration .

Uso:

Primero, esta es una function , no una secuencia de commands . Tienes que searchlos en tu session bash actual para poder usarlos.

 . elap.bash 

Sintaxis:

 elap [ [ -r | -R ] | [ -n ] [ -t | -T ] [<simple text report>] ] -r reset first counter only, don't output anything, like -R... -R reset both counters, (both -r and -R must by unique argument) -n don't reset any counter (just print) -t print both counters (reset first counter) -T print and reset 

Luego restablece ambos contadores antes de usarlo:

 elap -R find /usr/bin >/dev/null elap browsing /usr/bin 0.025389543 browsing /usr/bin 

Entonces, podrías agregar algunos marcadores en un script:

 #!/bin/bash . elap.bash elap -R tar -cf /tmp/test.tar -C / bin elap making a tarball of $(stat -c %s /tmp/test.tar) bytes gzip /tmp/test.tar elap compressing them to $(stat -c %s /tmp/test.tar.gz) bytes scp /tmp/test.tar.gz backup@elswhere.net:backups/ elap sending file to backup server rm /tmp/test.tar.gz elap removing compressed tarball elap -t total duration 0.043223957 making a tarball of 5877760 bytes 0.667249628 compressing them to 2742537 bytes test.tar.gz 100% 2678KB 2.6MB/s 00:00 0.380779818 sending file to backup server 0.010262259 removing compressed tarball 0.003566335 1.105081997 total duration 

Usar trap debug para seguir paso a paso

Con o sin el modificador -t , usando trap debug para paso a paso, con less alteración del guión (se agregaron cuatro líneas en la parte superior del guión y una en la parte inferior):

Como el reventado de la debugging ocurrirá antes $BASH_COMMAND ejecución de $BASH_COMMAND , debemos almacenar el contenido variable en una variable $BASH_LAST para una printing correcta, y agregar un command ficticio en la parte inferior de la secuencia de commands.

 #!/bin/bash . elap.bash elap -R export BASH_LAST=Starting trap 'elap -t $BASH_LAST;BASH_LAST=$BASH_COMMAND' debug tar -cf /tmp/test.tar -C / bin gzip /tmp/test.tar scp /tmp/test.tar.gz backup@elswhere.net:backups/ rm /tmp/test.tar.gz exit $? 

La exit $? Se necesita un command para volcar estadísticos después del último command rm .

  0.001011086 0.001011086 Starting 0.045175969 0.046187055 tar -cf /tmp/test.tar -C / bin 0.651394209 0.697581264 gzip /tmp/test.tar test.tar.gz 100% 2678KB 2.6MB/s 00:00 0.374499354 1.072080618 scp /tmp/test.tar.gz backup@elswhere.net:backups/ 0.007160101 1.079240719 rm /tmp/test.tar.gz 

La fuente de la function

Donde podría cortar (o reorderar) la parte de uptime , si prefiere usar la horquilla hasta la date +%s%N lugar de usar la granularidad de 1/100 de segundos.

 # # Bash source file for fine elapsed time reporting # based on /proc/timer_list, display elapsed time in nanosecs # or /proc/uptime if timer_list not present, for 100th of secs. # if none of them if present, fall back to *fork* `date +%s%N`. # # (C) 2011-2012 Felix Hauri - felix@f-hauri.ch # Licensed under terms of LGPL v3. www.gnu.org # Usage: # load script into bash using ``source elap.bash'' # # Syntaxe: elap [ [ -r | -R ] | [ -n ] [ -t | -T ] [<simple text report>] ] # -r reset first counter only, don't output anything, like -R... # -R reset both counters, (both -r and -R must by unique argument) # -n don't reset any counter (just print) # -t print both counters (reset first counter) # -T print and reset # # nota: using ``-n'' in combinaison with any of ``-r'' or ``-R'' is buggy. export _elaP_now _elaP_last _elaP_elap _elaP_last2 _elaP_dec if [ -r /proc/timer_list ] ;then _elaP_file=/proc/timer_list _elaP_dec=9 _elaP_field=2 mapfile < $_elaP_file _elaP_now _elaP_line=0 while [ "${_elaP_now[_elaP_line]}" == \ "${_elaP_now[_elaP_line]#*now at}" ] ;do ((_elaP_line++)) done eval 'function elap_getNow() { mapfile -n 1 -s '$_elaP_line' <'$_elaP_file' _elaP_now _elaP_now=($_elaP_now) _elaP_now=${_elaP_now[_elaP_field]} }' else # --- To be removed for nanoseconds only if [ -r /proc/uptime ] ;then _elaP_dec=2 function elap_getNow() { read -a _elaP_now </proc/uptime _elaP_now _elaP_now=${_elaP_now//./} } else # --- End of part to be removed for ns only. _elaP_dec=9 function elap_getNow() { _elaP_now=$(date +%s%N) ;} fi # --- Remove this line too for ns only. fi export -f elap_getNow elap() { local _Z9=000000000 local _elaP_setLast=true [ "$1" == "-n" ] && shift && _elaP_setLast=false [ "$2" == "-n" ] && set -- $1 ${@:3} && _elaP_setLast=false elap_getNow _elaP_elap=$((_elaP_now - _elaP_last)) [ ${#_elaP_elap} -lt $_elaP_dec ] && \ _elaP_elap=${_Z9:0:_elaP_dec-${#_elaP_elap}}$_elaP_elap [ "${*}" == "-R" ] && _elaP_last2=$_elaP_now || \ [ "${*}" == "-r" ] || if [ "$1" == "-t" ] || [ "$1" == "-T" ] ;then local _elaP_setLast2=false [ "$1" == "-T" ] && _elaP_setLast2=true shift _elaP_elap2=$((_elaP_now - _elaP_last2)) [ ${#_elaP_elap2} -lt $_elaP_dec ] && \ _elaP_elap2="${_Z9:0:_elaP_dec-${#_elaP_elap2}}$_elaP_elap2" printf "%6d.%s %6d.%s %s\n" \ "${_elaP_elap:0:${#_elaP_elap}-$_elaP_dec}" \ "${_elaP_elap:${#_elaP_elap}-_elaP_dec}" \ "${_elaP_elap2:0:${#_elaP_elap2}-$_elaP_dec}" \ "${_elaP_elap2:${#_elaP_elap2}-_elaP_dec}" "${*}" $_elaP_setLast2 && _elaP_last2=$_elaP_now else printf "%6d.%s %s\n" \ "${_elaP_elap:0:${#_elaP_elap}-$_elaP_dec}" \ "${_elaP_elap:${#_elaP_elap}-_elaP_dec}" "${*}" fi $_elaP_setLast && _elaP_last=$_elaP_now } export -f elap