Cosa significano “reale”, “utente” e “sys” nell’output del tempo (1)?

$ time foo real 0m0.003s user 0m0.000s sys 0m0.004s $ 

Cosa significano “reale”, “utente” e “sys” nell’output del tempo?

Quale è significativo quando esegui il benchmarking della mia app?

Real, User e Sys elaborano le statistiche temporali

Una di queste cose non è come le altre. Il reale si riferisce al tempo trascorso effettivo; Utente e Sys si riferiscono al tempo di CPU utilizzato solo dal processo.

  • Reale è l’ora dell’orologio a muro: il tempo dall’inizio alla fine della chiamata. Questo è tutto il tempo trascorso, comprese le fasce temporali utilizzate da altri processi e il tempo trascorso dal processo speso (ad esempio se è in attesa del completamento dell’I / O).

  • L’utente è la quantità di tempo impiegato dalla CPU nel codice in modalità utente (esterno al kernel) all’interno del processo. Questo è solo il tempo effettivo della CPU utilizzato nell’esecuzione del processo. Altri processi e tempi che il processo spende bloccati non contano per questa cifra.

  • Sys è la quantità di tempo della CPU speso nel kernel all’interno del processo. Ciò significa eseguire il tempo di CPU speso nelle chiamate di sistema all’interno del kernel, al contrario del codice della libreria, che è ancora in esecuzione nello spazio utente. Come “utente”, questa è solo la CPU utilizzata dal processo. Vedi sotto per una breve descrizione della modalità kernel (nota anche come modalità ‘supervisore’) e il meccanismo di chiamata di sistema.

User+Sys ti dirà quanto tempo effettivo della CPU utilizza il tuo processo. Si noti che questo è su tutte le CPU, quindi se il processo ha più thread (e questo processo è in esecuzione su un computer con più di un processore) potrebbe potenzialmente superare il tempo di wall clock riportato da Real (che di solito si verifica). Si noti che nell’output queste cifre includono il tempo User e Sys di tutti i processi figli (e dei loro discendenti) anche quando potrebbero essere stati raccolti, ad esempio in wait(2) o waitpid(2) , anche se le chiamate di sistema sottostanti restituiscono il statistiche per il processo e i suoi figli separatamente.

Origini delle statistiche riportate per time (1)

Le statistiche riportate dal time sono raccolte da varie chiamate di sistema. ‘Utente’ e ‘Sys’ provengono da wait (2) o times (2) , a seconda del particolare sistema. ‘Reale’ è calcolato a partire da un orario di inizio e di fine ottenuto dalla gettimeofday (2) . A seconda della versione del sistema, varie altre statistiche come il numero di opzioni di contesto possono anche essere raccolte nel time .

Su un computer multiprocessore, un processo multi-thread o un processo di forking per bambini potrebbe avere un tempo trascorso inferiore al tempo totale della CPU, poiché thread o processi diversi possono essere eseguiti in parallelo. Inoltre, le statistiche sul tempo riportate provengono da origini diverse, quindi i tempi registrati per attività di corsa molto brevi possono essere soggetti a errori di arrotondamento, come mostra l’esempio fornito dal poster originale.

Un breve primer sulla modalità Kernel vs. User

Su Unix, o qualsiasi sistema operativo con memoria protetta, la modalità ‘Kernel’ o ‘Supervisor’ fa riferimento a una modalità privilegiata in cui la CPU può operare. Determinate azioni privilegiate che potrebbero influenzare la sicurezza o la stabilità possono essere fatte solo quando la CPU sta operando in questa modalità; queste azioni non sono disponibili per il codice dell’applicazione. Un esempio di tale azione potrebbe essere la manipolazione della MMU per ottenere l’accesso allo spazio di indirizzamento di un altro processo. Normalmente, il codice in modalità utente non può farlo (a ragione), sebbene possa richiedere memoria condivisa dal kernel, che potrebbe essere letto o scritto da più di un processo. In questo caso, la memoria condivisa viene esplicitamente richiesta dal kernel attraverso un meccanismo sicuro ed entrambi i processi devono collegarsi esplicitamente ad esso per poterlo utilizzare.

La modalità privilegiata viene di solito definita modalità ‘kernel’ perché il kernel viene eseguito dalla CPU in esecuzione in questa modalità. Per passare alla modalità kernel devi emettere un’istruzione specifica (spesso chiamata trap ) che spinge la CPU a funzionare in modalità kernel ed esegue il codice da una posizione specifica contenuta in una tabella di salto. Per motivi di sicurezza, non è ansible passare alla modalità kernel ed eseguire codice arbitrario – i trap vengono gestiti tramite una tabella di indirizzi che non è ansible scrivere a meno che la CPU non sia in esecuzione in modalità supervisore. Tu intrappoli con un numero di trap esplicito e l’indirizzo viene cercato nella tabella dei salti; il kernel ha un numero finito di punti di ingresso controllati.

Le chiamate di “sistema” nella libreria C (in particolare quelle descritte nella sezione 2 delle pagine man) hanno un componente in modalità utente, che è ciò che chiamate effettivamente dal vostro programma C. Dietro le quinte, possono rilasciare una o più chiamate di sistema al kernel per eseguire servizi specifici come I / O, ma hanno anche il codice in esecuzione in modalità utente. È anche ansible rilasciare direttamente un trap alla modalità kernel da qualsiasi codice utente, se necessario, anche se potrebbe essere necessario scrivere uno snippet di linguaggio assembly per configurare correttamente i registri per la chiamata. Una pagina che descrive le chiamate di sistema fornite dal kernel di Linux e le convenzioni per l’impostazione dei registri può essere trovata qui.

Maggiori informazioni su ‘sys’

Ci sono cose che il tuo codice non può fare dalla modalità utente: cose come allocare memoria o accedere all’hardware (HDD, rete, ecc.). Questi sono sotto la supervisione del kernel, e solo lui può farli. Alcune operazioni che fai (come malloc o fread / fwrite ) invocheranno queste funzioni del Kernel e che quindi conteranno come il tempo di “sys”. Sfortunatamente non è così semplice come “ogni chiamata a malloc verrà conteggiata nel tempo di” sys “. La chiamata a malloc eseguirà una propria elaborazione (sempre conteggiata in “utente”) e quindi da qualche parte lungo il percorso potrebbe chiamare la funzione nel kernel (contata nel tempo di “sys”). Dopo il ritorno dalla chiamata del kernel, ci sarà ancora un po ‘di tempo in’ utente ‘e poi malloc tornerà al tuo codice. Per quanto riguarda il momento in cui avviene lo switch, e quanto viene speso in modalità kernel … non si può dire. Dipende dall’implementazione della libreria. Inoltre, altre funzioni apparentemente innocenti potrebbero utilizzare anche malloc e simili in background, che avranno di nuovo un po ‘di tempo in “sys”.

Per espandere la risposta accettata , volevo solo fornire un altro motivo per cui realuser + sys .

Tenere presente che il tempo real rappresenta il tempo trascorso effettivo, mentre user valori user e sys rappresentano il tempo di esecuzione della CPU. Di conseguenza, su un sistema multicore, l’ user e / o il tempo del sys (oltre alla loro sum) possono effettivamente superare il tempo reale. Ad esempio, su un’app Java che sto utilizzando per la class, ottengo questo insieme di valori:

 real 1m47.363s user 2m41.318s sys 0m4.013s 

Real mostra il tempo totale di turn-around per un processo; mentre l’utente mostra il tempo di esecuzione per le istruzioni definite dall’utente e Sys è giunto il momento di eseguire le chiamate di sistema!

Il tempo reale include anche il tempo di attesa (il tempo di attesa per I / O ecc.)

reale : il tempo effettivo trascorso nell’esecuzione del processo dall’inizio alla fine, come se fosse stato misurato da un umano con un cronometro

user : il tempo cumulativo trascorso da tutte le CPU durante il calcolo

sys : il tempo totale trascorso da tutte le CPU durante le attività relative al sistema, come l’allocazione della memoria.

Si noti che a volte l’utente + sys potrebbe essere maggiore del reale, in quanto più processori potrebbero funzionare in parallelo.