Misura il tempo in Linux - tempo vs orologio vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?


148

Tra le funzioni di temporizzazione, time, clock getrusage, clock_gettime, gettimeofdaye timespec_get, voglio capire chiaramente come la loro applicazione e quali sono i loro valori di ritorno in modo da sapere in quale situazione devo usarli.

Per prima cosa dobbiamo classificare le funzioni che restituiscono i valori dell'orologio da parete rispetto alle funzioni che restituiscono i valori di processo o thread . gettimeofdayrestituisce valore orologio a muro, clock_gettimerestituisce valore orologio a muro o processo o valori filati seconda del Clockparametro passato ad esso. getrusagee clockrestituisce valori di processo.

Quindi la seconda domanda riguarda l'implementazione di queste funzioni e, di conseguenza, la loro accuratezza. Quale meccanismo hardware o software utilizza queste funzioni.

Sembra che getrusageusi solo il tick del kernel (di solito lungo 1ms) e di conseguenza non può essere più preciso del ms. È giusto? Quindi la getimeofdayfunzione sembra utilizzare l'hardware sottostante più accurato disponibile. Di conseguenza la sua precisione è di solito il microsecondo (non può essere più a causa dell'API) sull'hardware recente. Che dire clock, la pagina man parla di "approssimazione", cosa significa? Che dire clock_gettime, l'API è in nanosecondi, significa che è in grado di essere così preciso se l'hardware sottostante lo consente? Che dire della monotonicità?

Ci sono altre funzioni?

Risposte:


198

Il problema è che ci sono diverse funzioni temporali disponibili in C e C ++ e alcune di esse variano nel comportamento tra le implementazioni. Ci sono anche molte mezze risposte che fluttuano intorno. Compilare un elenco di funzioni di clock insieme alle loro proprietà risponderebbe correttamente alla domanda. Per iniziare chiediamo quali sono le proprietà rilevanti che stiamo cercando. Guardando il tuo post, suggerisco:

  • A che ora è misurato l'orologio? (reale, utente, sistema o, si spera, orologio da parete?)
  • Qual è la precisione dell'orologio? (s, ms, µs o più veloce?)
  • Dopo quanto tempo passa l'orologio? O c'è qualche meccanismo per evitarlo?
  • L'orologio è monotonico o cambierà con le modifiche all'ora del sistema (tramite NTP, fuso orario, ora legale, da parte dell'utente, ecc.)?
  • In che modo quanto sopra varia tra le implementazioni?
  • La funzione specifica è obsoleta, non standard, ecc.?

Prima di iniziare l'elenco, vorrei sottolineare che l'ora dell'orologio a muro è raramente l'ora giusta da utilizzare, mentre cambia con le modifiche del fuso orario, dell'ora legale o se l'orologio a muro è sincronizzato da NTP. Nessuna di queste cose va bene se stai usando il tempo per pianificare eventi o per valutare le prestazioni. È davvero buono solo per quello che dice il nome, un orologio sul muro (o desktop).

Ecco cosa ho trovato finora per gli orologi in Linux e OS X:

  • time() restituisce l'ora dell'orologio da parete dal sistema operativo, con precisione in secondi.
  • clock()sembra restituire la somma del tempo dell'utente e del sistema. È presente in C89 e versioni successive. Un tempo si supponeva che questo fosse il tempo della CPU in cicli, ma gli standard moderni come POSIX richiedono che CLOCKS_PER_SEC sia 1000000, offrendo una precisione massima possibile di 1 µs. La precisione sul mio sistema è effettivamente di 1 µs. Questo orologio si avvolge una volta terminato (ciò accade in genere dopo ~ 2 ^ 32 tick, che non è molto lungo per un clock a 1 MHz). man clockdice che dal glibc 2.18 è implementato con clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)in Linux.
  • clock_gettime(CLOCK_MONOTONIC, ...)fornisce una risoluzione di nanosecondi, è monotonico. Credo che i "secondi" e i "nanosecondi" siano memorizzati separatamente, ciascuno in contatori a 32 bit. Pertanto, qualsiasi avvolgimento si verificherebbe dopo molte decine di anni di attività. Sembra un ottimo orologio, ma sfortunatamente non è ancora disponibile su OS X. POSIX 7 descrive CLOCK_MONOTONICcome estensione opzionale .
  • getrusage()si è rivelata la scelta migliore per la mia situazione. Riporta separatamente i tempi dell'utente e del sistema e non va a finire. La precisione sul mio sistema è di 1 µs, ma l'ho anche testata su un sistema Linux (Red Hat 4.1.2-48 con GCC 4.1.2) e lì la precisione era solo 1 ms.
  • gettimeofday()restituisce l'ora dell'orologio da parete con precisione (nominale) µs. Sul mio sistema questo orologio sembra avere una precisione di µs, ma questo non è garantito, perché "la risoluzione dell'orologio di sistema dipende dall'hardware" . POSIX.1-2008 dice questo . "Le applicazioni dovrebbero usare la clock_gettime()funzione invece della gettimeofday()funzione obsolescente ", quindi dovresti starne alla larga. Linux x86 e lo implementa come una chiamata di sistema .
  • mach_absolute_time()è un'opzione per il timing ad altissima risoluzione (ns) su OS X. Sul mio sistema, questo offre effettivamente una risoluzione ns. In linea di principio questo orologio si avvolge, tuttavia sta memorizzando ns utilizzando un numero intero senza segno a 64 bit, quindi il wrapping non dovrebbe essere un problema in pratica. La portabilità è discutibile.
  • Ho scritto una funzione ibrida basata su questo frammento che utilizza clock_gettime quando compilato su Linux o un timer Mach quando compilato su OS X, al fine di ottenere la precisione ns sia su Linux che su OS X.

Tutto quanto sopra esiste sia in Linux che in OS X, salvo dove diversamente specificato. "Il mio sistema" sopra è Apple con OS X 10.8.3 con GCC 4.7.2 di MacPorts.

Infine, ecco un elenco di riferimenti che ho trovato utili in aggiunta ai collegamenti sopra:


Aggiornamento : per OS X, clock_gettimeè stato implementato dal 10.12 (Sierra). Inoltre, entrambe le piattaforme POSIX e BSD (come OS X) condividono il rusage.ru_utimecampo struct.


Mac OS X non ha clock_gettime, quindi l'uso di gettimeofday()essere un po 'più versatile diclock_gettime()
bobobobo

1
Non hai menzionato times()(con un / i), che esiste in POSIX dal numero 1. Riguardo a GNU / Linux: Secondo la pagina man clock (3), clock()da glibc 2.17 e precedenti è stato implementato sopra di esso, ma per migliorare precisione, ora è implementato sopra clock_gettime(CLOCK_PROCESS_CPUTIME_ID,...), che è anche specificato in POSIX ma è facoltativo.
vinc17,

2
@starflyer La precisione dell'orologio è in parte limitata dal tempo necessario per eseguire il polling dell'orologio. Questo perché, se chiamo l'orologio e ci vogliono 1 µs per tornare, allora il tempo che l'orologio segnala sarà "spento" di 1 µs dal punto di vista del chiamante. Ciò significa che anche un orologio ad alta precisione deve essere a bassa latenza. Quindi in genere uno non avrà il compromesso di cui stai parlando: gli orologi più economici saranno anche i più precisi.
Douglas B. Staple,

3
Inoltre, la maggior parte degli orologi non si preoccupa dell'ora legale / dei fusi orari, anche se sono considerati orologi da parete . Entrambi timee gettimeofdayritornano, almeno al giorno d'oggi, secondi dall'epoca (ovvero unix-timestamps). Questo è indipendente dai fusi orari / DST. I secondi di salto sono un'altra storia ...
Zulan

2
Per gli utenti Android, l'utilizzo di CLOCK_MONOTONIC può essere problematico poiché l'app potrebbe essere sospesa, insieme all'orologio. Per questo, Android ha aggiunto il timer ANDROID_ALARM_ELAPSED_REALTIME accessibile tramite ioctl. alcune informazioni su queste e altre informazioni relative alla sospensione sono disponibili qui
Itay Bianco,

17

C11 timespec_get

Esempio di utilizzo su: https://stackoverflow.com/a/36095407/895245

La massima precisione possibile restituita è di nanosecondi, ma la precisione effettiva è definita dall'implementazione e potrebbe essere inferiore.

Restituisce il tempo di wall, non l'utilizzo della CPU.

glibc 2.21 lo implementa sotto sysdeps/posix/timespec_get.ce lo inoltra direttamente a:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettimee CLOCK_REALTIMEsono POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html e man clock_gettimeafferma che questa misura potrebbe presentare discontinuità se si modifica l'impostazione dell'ora di sistema durante l'esecuzione del programma.

C ++ 11 chrono

Dal momento che ci siamo, copriamoli anche: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C ++ stdlib è all'interno della sorgente GCC):

  • high_resolution_clock è un alias per system_clock
  • system_clock inoltra alla prima delle seguenti opzioni disponibili:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock inoltra alla prima delle seguenti opzioni disponibili:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

Chiesto a: Differenza tra std :: system_clock e std :: steady_clock?

CLOCK_REALTIMEvs CLOCK_MONOTONIC: differenza tra CLOCK_REALTIME e CLOCK_MONOTONIC?


1
Ottima risposta che demistifica le implementazioni tipiche. Questo è ciò che le persone hanno davvero bisogno di sapere.
Celess,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.