¿Quiere saber cuánto tiempo dura un procedimiento y mucho más? El Linux time
El comando devuelve estadísticas de tiempo, lo que le brinda información interesante sobre los recursos utilizados por sus programas.
el tiempo tiene muchos familiares
Hay muchas distribuciones de Linux y diferentes sistemas operativos similares a Unix. Cada uno de estos tiene un shell de comandos predeterminado. El shell predeterminado más común en las distribuciones modernas de Linux es el shell bash. Pero hay muchos otros, como el shell Z (zsh) y el shell Korn (ksh).
Todas estas conchas incorporan sus propias time
comando, ya sea como un incorporado comando o como un palabra reservada. Cuando escribes time
en una ventana de terminal, el shell ejecutará su comando interno en lugar de utilizar GNU time
binario que se proporciona como parte de su distribución de Linux.
Queremos utilizar la versión GNU de time
debido a que tiene mas opciones y es más flexible.
¿A qué hora correrá?
Puede chequear qué versión se ejecutará usando el type
mando. type
le permitirá saber si el shell manejará sus instrucciones por sí mismo, con sus rutinas internas, o las pasará al binario GNU.
en una ventana de terminal escribe la palabra type
, un espacio y después la palabra time
y presione Enter.
type time
Podemos ver eso en el shell bash time
es una palabra reservada. Esto significa que Bash utilizará sutime
rutinas por defecto.
type time
En el shell Z (zsh) time
es una palabra reservada, por lo que las rutinas de shell internas se utilizarán de forma predeterminada.
type time
En el caparazón de Korn time
es una keyword. Se utilizará una rutina interna en lugar de GNU time
mando.
RELACIONADO: ¿Qué es ZSH y por qué debería usarlo en lugar de Bash?
Ejecutando el comando GNU time
Si el shell de su sistema Linux tiene un time
rutina tendrá que ser explícito si desea usar el GNU time
binario. Debes:
- Proporcione la ruta completa al binario, como
/usr/bin/time
. Ejecutar elwhich time
comando para hallar esta ruta. - Utilizar
command time
. - Use una barra invertida como
time
.
los which time
El comando nos da la ruta al binario.
Podemos probar esto usando /usr/bin/time
como un comando para iniciar el binario GNU. Eso funciona. Recibimos una respuesta del time
comando que nos dice que no proporcionamos ningún parámetro de línea de comando para que funcione.
Mecanografía command time
además funciona, y obtenemos la misma información de uso de time
. los command
comando le dice al shell que ignore el siguiente comando para que se procese fuera del shell.
Usando un carácter antes del nombre del comando es lo mismo que utilizar
command
antes del nombre del comando.
La forma más sencilla de asegurarse de que está usando GNU time
binary es utilizar la opción de barra invertida.
time
time
time
invoca el cascarón versión del tiempo. time
utiliza el time
binario.
Usando el comando de tiempo
Midamos algunos programas. Estamos usando dos programas llamados loop1
y loop2
. Fueron creados a partir de loop1.cy loop2.c. No hacen nada útil aparte de demostrar los efectos de un tipo de ineficiencia de codificación.
Este es loop1.c. Se necesita la longitud de una cuerda dentro de los dos bucles anidados. La longitud se obtiene de antemano, fuera de los dos bucles anidados.
#include "stdio.h" #include "string.h" #include "stdlib.h" int main (int argc, char* argv[]) { int i, j, len, count=0; char szString[]="how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek"; // get length of string once, outside of loops len = strlen( szString ); for (j=0; j<500000; j++) { for (i=0; i < len; i++ ) { if (szString[i] == '-') count++; } } printf("Counted %d hyphensn", count); exit (0); } // end of main
Este es loop2.c. La longitud de la cuerda se obtiene una y otra vez para cada ciclo del bucle exterior. Esta ineficiencia debería reflejarse en los tiempos.
#include "stdio.h" #include "string.h" #include "stdlib.h" int main (int argc, char* argv[]) { int i, j, count=0; char szString[]="how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek"; for (j=0; j<500000; j++) { // getting length of string every // time the loops trigger for (i=0; i < strlen(szString); i++ ) { if (szString[i] == '-') count++; } } printf("Counted %d hyphensn", count); exit (0); } // end of main
Vamos a encender el loop1
programar y utilizar time
para medir su desempeño.
time ./loop1
Ahora hagamos lo mismo por loop2
.
time ./loop2
Eso nos ha dado dos conjuntos de resultados, pero están en un formato verdaderamente desagradable. Podemos hacer algo al respecto más tarde, pero escojamos algunos bits de información de los resultados.
Cuando los programas se ejecutan, hay dos modos de ejecución entre los que se alternan. Estos se llaman modo de usuario y modo kernel.
Resumidamente, un procedimiento en modo de usuario no puede tener acceso de forma directa al hardware o la memoria de referencia fuera de su propia asignación. Para obtener acceso a dichos recursos, el procedimiento debe realizar solicitudes al kernel. Si el kernel aprueba la solicitud, el procedimiento entra en ejecución en modo kernel hasta que se satisfaga el requisito. A continuación, el procedimiento vuelve a la ejecución en modo de usuario.
Los resultados para loop1
dinos eso loop1
pasó 0,09 segundos en modo de usuario. O pasó cero tiempo en modo kernel o el tiempo en modo kernel es un valor demasiado bajo para registrarlo una vez que se ha redondeado hacia abajo. El tiempo total transcurrido fue de 0,1 segundos. loop1
recibió un promedio del 89% del tiempo de CPU a lo largo del tiempo total transcurrido.
El ineficiente loop2
El programa tardó tres veces más en ejecutarse. Su tiempo total transcurrido es de 0,3 segundos. La duración del tiempo de procesamiento en el modo de usuario es de 0,29 segundos. Nada se registra para el modo kernel. loop2
recibió un promedio del 96% del tiempo de CPU durante su ejecución.
Formatear la salida
Puede personalizar la salida desde time
usando una cadena de formato. La cadena de formato puede contener texto y especificadores de formato. La lista de especificadores de formato puede ser que se encuentra en la página del manual por time
. Cada uno de los especificadores de formato representa un fragmento de información.
Cuando se imprime la cadena, los especificadores de formato se reemplazan por los valores reales que representan. A modo de ejemplo, el especificador de formato para el porcentaje de CPU es la letra P
. Para indicar a time
que un especificador de formato no es solo una letra normal, agréguele un signo de porcentaje, como %P
. Usémoslo en un ejemplo.
los -f
La opción (cadena de formato) se utiliza para indicar time
que lo que sigue es una cadena de formato.
Nuestra cadena de formato imprimirá los caracteres “Programa:” y el nombre del programa (y cualquier parámetro de línea de comando que le pase al programa). los %C
El especificador de formato significa «Nombre y argumentos de la línea de comandos del comando que se está cronometrando». los n
hace que la salida se mueva a la próxima línea.
Hay muchos especificadores de formatos y distinguen entre mayúsculas y minúsculas, por lo tanto asegúrese de ingresarlos correctamente cuando lo haga por sí mismo.
A continuación, imprimiremos los caracteres «Tiempo total:» seguido del valor del tiempo total transcurrido para esta ejecución del programa (representado por %E
).
Usamos n
para dar otra nueva línea. A continuación, imprimiremos los caracteres «Modo (s) de usuario», seguidos del valor del tiempo de CPU empleado en el modo de usuario, representado por el %U
.
Usamos n
para dar otra nueva línea. Esta vez nos estamos preparando para el valor de tiempo del kernel. Imprimimos los caracteres «Kernel Mode (s)», seguidos del especificador de formato para el tiempo de CPU empleado en modo kernel, que es %S
.
Por último, vamos a imprimir los caracteres «n
CPU: ”para darnos una nueva línea y el título de este valor de datos. los %P
El especificador de formato dará el porcentaje promedio de tiempo de CPU utilizado por el procedimiento temporizado.
Toda la cadena de formato está entre comillas. Podríamos haber incluido algunos t
caracteres para colocar pestañas en la salida si somos quisquillosos con la alineación de los valores.
time -f "Program: %CnTotal time: %EnUser Mode (s) %UnKernel Mode (s) %SnCPU: %P" ./loop1
Enviar la salida a un archivo
Para mantener un registro de los tiempos de las pruebas que ha realizado, puede enviar la salida desde time
a un archivo. Para hacer esto use el -o
(salida) opción. La salida de su programa seguirá mostrándose en la ventana de la terminal. Es solo la salida de time
que se redirige al archivo.
Podemos volver a ejecutar la prueba y guardar la salida en el test_results.txt
archivo de la próxima manera:
time -o test_results.txt -f "Program: %CnTotal time: %EnUser Mode (s) %UnKernel Mode (s) %SnCPU: %P" ./loop1
cat test_results.txt
los loop1
La salida del programa se muestra en la ventana del terminal y los resultados de time
Ve a la test_results.txt
expediente.
Si desea capturar el siguiente conjunto de resultados en el mismo archivo, debe usar la -a
(añadir) opción de la próxima manera:
time -o test_results.txt -a -f "Program: %CnTotal time: %EnUser Mode (s) %UnKernel Mode (s) %SnCPU: %P" ./loop2
cat test_results.txt
Ahora debería ser evidente por qué usamos el %C
especificador de formato para incluir el nombre del programa en la salida de la cadena de formato.
Y estamos fuera de tiempo
Probablemente de mayor utilidad para programadores y desarrolladores para ajustar su código, el time
El comando además es útil para cualquiera que desee descubrir un poco más sobre lo que sucede debajo del capó cada vez que inicia un programa.