$ time foo
real 0m0.003s
user 0m0.000s
sys 0m0.004s
$
¿Qué significan 'real', 'usuario' y 'sys' en la salida del tiempo?
¿Cuál es significativo al comparar mi aplicación?
unix
time
benchmarking
rayryeng
fuente
fuente
time
, haga que haga algo que tome al menos un segundo.time
es una palabra clave bash. Por lo que escribirman time
es que no le da una página del manual para la fiestatime
, más bien se está dando a la página del manual/usr/bin/time
. Esto me ha hecho tropezar.Respuestas:
Estadísticas de tiempo de proceso real, usuario y sistema
Una de estas cosas no es como la otra. Real se refiere al tiempo transcurrido real; Usuario y Sys se refieren al tiempo de CPU utilizado solo por el proceso.
Real es la hora del reloj de pared: tiempo desde el inicio hasta el final de la llamada. Este es todo el tiempo transcurrido, incluidos los segmentos de tiempo utilizados por otros procesos y el tiempo que el proceso pasa bloqueado (por ejemplo, si está esperando que se complete la E / S).
Usuario es la cantidad de tiempo de CPU gastado en código de modo de usuario (fuera del núcleo) dentro del proceso. Este es solo el tiempo real de CPU utilizado en la ejecución del proceso. Otros procesos y el tiempo que el proceso pasa bloqueado no cuentan para esta cifra.
Sys es la cantidad de tiempo de CPU que se pasa en el núcleo dentro del proceso. Esto significa ejecutar el tiempo de CPU gastado en las llamadas del sistema dentro del núcleo, a diferencia del código de la biblioteca, que todavía se ejecuta en el espacio del usuario. Al igual que 'usuario', este es solo el tiempo de CPU utilizado por el proceso. Consulte a continuación una breve descripción del modo kernel (también conocido como modo 'supervisor') y el mecanismo de llamada del sistema.
User+Sys
le dirá cuánto tiempo real de CPU usó su proceso. Tenga en cuenta que estoReal
ocurre en todas las CPU, por lo que si el proceso tiene varios subprocesos (y este proceso se ejecuta en una computadora con más de un procesador), podría exceder el tiempo de reloj de pared informado (que generalmente ocurre). Tenga en cuenta que en el resultado estas cifras incluyen el tiempoUser
y elSys
tiempo de todos los procesos secundarios (y sus descendientes), así como cuándo podrían haberse recopilado, por ejemplo, mediantewait(2)
owaitpid(2)
, aunque las llamadas al sistema subyacentes devuelven las estadísticas del proceso y sus elementos secundarios por separado.Orígenes de las estadísticas reportadas por
time (1)
Las estadísticas informadas por
time
se recopilan de varias llamadas al sistema. 'Usuario' y 'Sys' provienen dewait (2)
( POSIX ) otimes (2)
( POSIX ), dependiendo del sistema en particular. 'Real' se calcula a partir de una hora de inicio y finalización recopilada de lagettimeofday (2)
llamada. Dependiendo de la versión del sistema, también se pueden recopilar otras estadísticas como el número de cambios de contextotime
.En una máquina multiprocesador, un proceso multiproceso o un proceso que bifurca a los niños podría tener un tiempo transcurrido menor que el tiempo total de la CPU, ya que diferentes subprocesos o procesos pueden ejecutarse en paralelo. Además, las estadísticas de tiempo informadas provienen de diferentes orígenes, por lo que los tiempos registrados para tareas de ejecución muy cortas pueden estar sujetos a errores de redondeo, como muestra el ejemplo dado por el póster original.
Una breve introducción sobre el modo Kernel vs. Usuario
En Unix, o en cualquier sistema operativo de memoria protegida, el modo 'Kernel' o 'Supervisor' se refiere a un modo privilegiado en el que la CPU puede operar. Ciertas acciones privilegiadas que podrían afectar la seguridad o la estabilidad solo pueden realizarse cuando la CPU está operando en este modo Estas acciones no están disponibles para el código de la aplicación. Un ejemplo de tal acción podría ser la manipulación de la MMU para obtener acceso al espacio de direcciones de otro proceso. Normalmente, el código de modo de usuario no puede hacer esto (con buena razón), aunque puede solicitar memoria compartida del núcleo, lo que podríaser leído o escrito por más de un proceso. En este caso, la memoria compartida se solicita explícitamente desde el núcleo a través de un mecanismo seguro y ambos procesos deben adjuntarse explícitamente para poder usarla.
El modo privilegiado generalmente se conoce como modo 'núcleo' porque el núcleo lo ejecuta la CPU que se ejecuta en este modo. Para cambiar al modo kernel, debe emitir una instrucción específica (a menudo llamada trampa ) que cambia la CPU para que se ejecute en modo kernel y ejecuta código desde una ubicación específica contenida en una tabla de salto. Por razones de seguridad, no puede cambiar al modo kernel y ejecutar código arbitrario: las trampas se administran a través de una tabla de direcciones en las que no se puede escribir a menos que la CPU se ejecute en modo supervisor. Atrapa con un número de trampa explícito y la dirección se busca en la tabla de salto; el núcleo tiene un número finito de puntos de entrada controlados.
Las llamadas al 'sistema' en la biblioteca C (particularmente las descritas en la Sección 2 de las páginas del manual) tienen un componente de modo de usuario, que es lo que realmente llama desde su programa C. Detrás de escena, pueden emitir una o más llamadas del sistema al núcleo para realizar servicios específicos como E / S, pero también tienen código ejecutándose en modo de usuario. También es bastante posible emitir directamente una trampa al modo kernel desde cualquier código de espacio de usuario si lo desea, aunque es posible que deba escribir un fragmento de lenguaje ensamblador para configurar los registros correctamente para la llamada.
Más acerca de 'sys'
Hay cosas que su código no puede hacer desde el modo de usuario, como asignar memoria o acceder al hardware (HDD, red, etc.). Estos están bajo la supervisión del núcleo, y solo ellos pueden hacerlos. Algunas operaciones como
malloc
ofread
/fwrite
invocarán estas funciones del núcleo y luego contarán como tiempo 'sys'. Desafortunadamente, no es tan simple como "cada llamada a malloc se contará en el tiempo 'sys'". La llamada amalloc
realizará un procesamiento propio (todavía contado en el tiempo del 'usuario') y luego en algún punto del camino puede llamar a la función en el núcleo (contado en el tiempo 'sys'). Después de regresar de la llamada del kernel, habrá más tiempo en 'usuario' y luegomalloc
volverá a su código En cuanto a cuándo ocurre el cambio, y cuánto se gasta en modo kernel ... no se puede decir. Depende de la implementación de la biblioteca. Además, otras funciones aparentemente inocentes también podrían usarmalloc
y similares en el fondo, que nuevamente tendrá algo de tiempo en 'sys'.fuente
Para ampliar la respuesta aceptada , solo quería proporcionar otra razón por la cual
real
≠user
+sys
.Tenga en cuenta que
real
representa el tiempo transcurrido real, mientras queuser
ysys
valores representan el tiempo de ejecución de la CPU. Como resultado, en un sistema multinúcleo, el tiempouser
y / osys
tiempo (así como su suma) pueden exceder el tiempo real. Por ejemplo, en una aplicación Java que estoy ejecutando para la clase, obtengo este conjunto de valores:fuente
real
excedenteuser
ysys
total? La sobrecarga del sistema operativo, como el cambio de contexto de subproceso puede ser?• real : el tiempo real empleado en ejecutar el proceso de principio a fin, como si lo midiera un humano con un cronómetro
• usuario : el tiempo acumulado empleado por todas las CPU durante el cálculo
• sys : el tiempo acumulado que pasan todas las CPU durante las tareas relacionadas con el sistema, como la asignación de memoria.
fuente
sys
¿Se pasa tiempo de CPU en llamadas al sistema (y manejadores de fallas de página?)real
a menudo se describe como tiempo de "reloj de pared".Ejemplos mínimos de POSIX C ejecutables
Para hacer las cosas más concretas, quiero ejemplificar algunos casos extremos
time
con algunos programas mínimos de prueba C.Todos los programas se pueden compilar y ejecutar con:
y han sido probados en Ubuntu 18.10, GCC 8.2.0, glibc 2.28, Linux kernel 4.18, laptop ThinkPad P51, CPU Intel Core i7-7820HQ (4 núcleos / 8 hilos), 2x Samsung M471A2K43BB1-CRC RAM (2x 16GiB).
dormir
El sueño no ocupado no cuenta en ninguno
user
osys
soloreal
.Por ejemplo, un programa que duerme un segundo:
GitHub aguas arriba .
produce algo como:
Lo mismo vale para los programas bloqueados cuando IO está disponible.
Por ejemplo, el siguiente programa espera a que el usuario ingrese un carácter y presione enter:
GitHub aguas arriba .
Y si espera aproximadamente un segundo, se genera como en el ejemplo de reposo algo así como:
Por esta razón,
time
puede ayudarlo a distinguir entre los programas vinculados a la CPU y a las E / S: ¿Qué significan los términos "CPU vinculados" y "E / S atados"?Hilos múltiples
El siguiente ejemplo realiza
niters
iteraciones de trabajo inútil puramente vinculado a la CPU ennthreads
subprocesos:GitHub upstream + código de trama .
Luego graficamos wall, user y sys en función del número de subprocesos para un 10 ^ 10 iteraciones fijas en mi 8 CPU hyperthread:
Trazar datos .
Del gráfico, vemos que:
para una aplicación de núcleo único intensivo de CPU, el muro y el usuario son casi lo mismo
para 2 núcleos, el usuario mide aproximadamente 2 veces la pared, lo que significa que el tiempo del usuario se cuenta en todos los subprocesos.
El usuario básicamente se duplicó, y mientras que la pared se mantuvo igual.
esto continúa hasta 8 subprocesos, lo que coincide con mi número de hyperthreads en mi computadora.
Después de 8, el muro comienza a aumentar también, ¡porque no tenemos CPU adicionales para poner más trabajo en un período de tiempo determinado!
La relación se estabiliza en este punto.
Tenga en cuenta que este gráfico es tan claro y simple porque el trabajo está puramente vinculado a la CPU: si estuviera vinculado a la memoria, obtendríamos una caída en el rendimiento mucho antes con menos núcleos porque los accesos a la memoria serían un cuello de botella como se muestra en What Qué significan los términos "enlazado a la CPU" y "enlazado de E / S"?
Sys trabajo pesado con
sendfile
La carga de trabajo de sys más pesada que se me ocurrió fue usar el
sendfile
, que realiza una operación de copia de archivos en el espacio del kernel: copie un archivo de una manera sana, segura y eficienteAsí que imaginé que este en el núcleo
memcpy
será una operación intensiva de la CPU.Primero inicializo un gran archivo aleatorio de 10GiB con:
Luego ejecuta el código:
GitHub aguas arriba .
que proporciona básicamente el tiempo del sistema como se esperaba:
También tenía curiosidad por ver si
time
distinguiría entre syscalls de diferentes procesos, así que intenté:Y el resultado fue:
El tiempo del sistema es casi el mismo para ambos que para un solo proceso, pero el tiempo del muro es mayor porque los procesos compiten por un acceso de lectura de disco probable.
Por lo tanto, parece que de hecho explica qué proceso inició un trabajo de núcleo dado.
Código fuente de Bash
Cuando lo hace solo
time <cmd>
en Ubuntu, usa la palabra clave Bash como se puede ver en:que salidas:
Entonces grep fuente en el código fuente Bash 4.19 para la cadena de salida:
lo que nos lleva a la función execute_cmd.c
time_command
, que usa:gettimeofday()
ygetrusage()
si ambos están disponiblestimes()
de otra maneratodos los cuales son llamadas al sistema Linux y funciones POSIX .
Código fuente de GNU Coreutils
Si lo llamamos como:
entonces usa la implementación GNU Coreutils.
Este es un poco más complejo, pero la fuente relevante parece estar en resuse.c y lo hace:
wait3
llamada BSD no POSIX si está disponibletimes
y de logettimeofday
contrariofuente
Real muestra el tiempo total de respuesta para un proceso; mientras que el usuario muestra el tiempo de ejecución de las instrucciones definidas por el usuario y Sys es el tiempo para ejecutar las llamadas al sistema.
El tiempo real también incluye el tiempo de espera (el tiempo de espera para E / S, etc.)
fuente