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 in giro. La compilazione di un elenco di funzioni dell'orologio insieme alle loro proprietà risponderebbe correttamente alla domanda. Per iniziare chiediamo quali sono le proprietà pertinenti che stiamo cercando. Guardando il tuo post, suggerisco:
- Che ora è misurata dall'orologio? (reale, utente, sistema o, si spera no, orologio da parete?)
- Qual è la precisione dell'orologio? (s, ms, µs o più veloce?)
- Dopo quanto tempo finisce l'orologio? O c'è qualche meccanismo per evitarlo?
- L'orologio è monotono o cambierà con i cambiamenti dell'ora di sistema (tramite NTP, fuso orario, ora legale, dall'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 da parete è raramente l'ora giusta da utilizzare, mentre cambia con i cambi di fuso orario, i cambiamenti dell'ora legale o se l'orologio da parete è sincronizzato da NTP. Nessuna di queste cose va bene se stai usando il tempo per programmare eventi o per confrontare le prestazioni. È davvero buono solo per quello che dice il nome, un orologio sul muro (o sul 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 dell'ora dell'utente e del sistema. È presente in C89 e successivi. Un tempo questo doveva essere il tempo della CPU in cicli, ma gli standard moderni come POSIX richiedono che CLOCKS_PER_SEC sia 1000000, fornendo una precisione massima possibile di 1 µs. La precisione sul mio sistema è infatti di 1 µs. Questo clock si avvolge una volta raggiunto il massimo (questo in genere accade dopo ~ 2 ^ 32 tick, che non è molto lungo per un clock da 1 MHz).man clock
dice che dalla glibc 2.18 è implementato conclock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)
su Linux.clock_gettime(CLOCK_MONOTONIC, ...)
fornisce una risoluzione di nanosecondi, è monotona. Credo che i "secondi" e i "nanosecondi" siano memorizzati separatamente, ciascuno in contatori a 32 bit. Pertanto, qualsiasi conclusione si verificherebbe dopo molte dozzine di anni di attività. Sembra un ottimo orologio, ma sfortunatamente non è ancora disponibile su OS X. POSIX 7 descriveCLOCK_MONOTONIC
come estensione facoltativa.getrusage()
si è rivelata la scelta migliore per la mia situazione. Riporta separatamente l'ora dell'utente e del sistema e non esegue il wrapping. La precisione sul mio sistema è di 1 µs, ma l'ho testata anche su un sistema Linux (Red Hat 4.1.2-48 con GCC 4.1.2) e lì la precisione era solo di 1 ms.gettimeofday()
restituisce l'ora dell'orologio da parete con (nominalmente) precisione µs. Sul mio sistema questo orologio sembra avere una precisione µs, ma questo non è garantito, perché "la risoluzione dell'orologio di sistema dipende dall'hardware". POSIX.1-2008 lo dice. "Le applicazioni devono utilizzare ilclock_gettime()
funzione invece dell'obsoletogettimeofday()
function", quindi dovresti starne alla larga. Linux x86 e lo implementa come chiamata di sistema.mach_absolute_time()
è un'opzione per la temporizzazione ad altissima risoluzione (ns) su OS X. Sul mio sistema, questo dà effettivamente una risoluzione ns. In linea di principio questo orologio si avvolge, tuttavia memorizza ns utilizzando un numero intero senza segno a 64 bit, quindi in pratica il wrapping non dovrebbe essere un problema. La portabilità è discutibile.- Ho scritto una funzione ibrida basata su questo frammento che usa clock_gettime se compilato su Linux, o un timer Mach se compilato su OS X, per ottenere la precisione ns sia su Linux che su OS X.
Tutto quanto sopra esiste sia in Linux che in OS X tranne dove diversamente specificato. "Il mio sistema" in quanto sopra è un Apple con OS X 10.8.3 con GCC 4.7.2 da MacPorts.
Infine, ecco un elenco di riferimenti che ho trovato utili in aggiunta ai link precedenti:
- http://blog.habets.pp.se/2010/09/gettimeofday-should-never-be-used-to-measure-time
- Come misurare il tempo di esecuzione EFFETTIVO di un programma C sotto Linux?
- http://digitalsandwich.com/archives/27-benchmarking-misconceptions-microtime-vs-getrusage.html
- http://www.unix.com/hp-ux/38937-getrusage.html
Aggiorna :per OS X, clock_gettime
è stato implementato dalla 10.12 (Sierra). Inoltre, entrambe le piattaforme basate su POSIX e BSD (come OS X) condividono il rusage.ru_utime
campo struct.
C11 timespec_get
Esempio di utilizzo su:https://stackoverflow.com/a/36095407/895245
La precisione massima possibile restituita è di nanosecondi, ma la precisione effettiva è definita dall'implementazione e potrebbe essere inferiore.
Restituisce il tempo di visualizzazione, non l'utilizzo della CPU.
glibc 2.21 lo implementa sotto sysdeps/posix/timespec_get.c
e inoltra direttamente a:
clock_gettime (CLOCK_REALTIME, ts) < 0)
clock_gettime
e CLOCK_REALTIME
sono POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html e man clock_gettime
dice che questa misura potrebbe avere discontinuità se modifichi alcune impostazioni dell'ora di sistema mentre il tuo programma è in esecuzione.
cronometro C++11
Visto che ci siamo, copriamo anche loro:http://en.cppreference.com/w/cpp/chrono
GCC 5.3.0 (C++ stdlib è all'interno del sorgente GCC):
high_resolution_clock
è un alias persystem_clock
system_clock
inoltra al primo dei seguenti elementi disponibili:clock_gettime(CLOCK_REALTIME, ...)
gettimeofday
time
steady_clock
inoltra al primo dei seguenti elementi disponibili:clock_gettime(CLOCK_MONOTONIC, ...)
system_clock
Domanda a:Differenza tra std::system_clock e std::steady_clock?
CLOCK_REALTIME
rispetto a CLOCK_MONOTONIC
:Differenza tra CLOCK_REALTIME e CLOCK_MONOTONIC?