C ++ ottenendo tempi di millisecondi su Linux – clock () non sembra funzionare correttamente

Su Windows, clock() restituisce il tempo in millisecondi, ma su questo box Linux su cui sto lavorando, lo arrotonda al 1000 più vicino quindi la precisione è solo al livello “secondo” e non al livello di millisecondi.

Ho trovato una soluzione con Qt usando la class QTime , istanziando un object e chiamando start() su di esso, quindi chiamando il tempo elapsed() per ottenere il numero di millisecondi trascorsi.

Ho avuto una fortuna perché sto lavorando con Qt per cominciare, ma mi piacerebbe una soluzione che non si basasse su librerie di terze parti,

Non esiste un modo standard per farlo?

AGGIORNARE

Si prega di non raccomandare Boost ..

Se Boost e Qt possono farlo, sicuramente non è magico, ci deve essere qualcosa di standard che stanno usando!

È ansible utilizzare gettimeofday all’inizio e alla fine del metodo e quindi fare la differenza tra le due strutture di restituzione. Otterrai una struttura come la seguente:

 struct timeval { time_t tv_sec; suseconds_t tv_usec; } 
 #include  #include  #include  int main() { struct timeval start, end; long mtime, seconds, useconds; gettimeofday(&start, NULL); usleep(2000); gettimeofday(&end, NULL); seconds = end.tv_sec - start.tv_sec; useconds = end.tv_usec - start.tv_usec; mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; printf("Elapsed time: %ld milliseconds\n", mtime); return 0; } 

Si prega di notare che l’ clock non misura l’ora dell’orologio a muro. Ciò significa che se il tuo programma impiega 5 secondi, l’ clock non misurerà necessariamente 5 secondi, ma potrebbe essere più (il tuo programma potrebbe eseguire più thread e quindi potrebbe consumare più CPU del tempo reale) o meno. Misura un’approssimazione del tempo di CPU utilizzato. Per vedere la differenza, considera questo codice

 #include  #include  #include  int main() { std::clock_t a = std::clock(); sleep(5); // sleep 5s std::clock_t b = std::clock(); std::cout < < "difference: " << (b - a) << std::endl; return 0; } 

Emette sul mio sistema

 $ difference: 0 

Perché tutto quello che abbiamo fatto è stato dormire e non usare il tempo della CPU! Tuttavia, usando gettimeofday otteniamo ciò che vogliamo (?)

 #include  #include  #include  #include  int main() { timeval a; timeval b; gettimeofday(&a, 0); sleep(5); // sleep 5s gettimeofday(&b, 0); std::cout < < "difference: " << (b.tv_sec - a.tv_sec) << std::endl; return 0; } 

Uscite sul mio sistema

 $ difference: 5 

Se hai bisogno di maggiore precisione ma vuoi ottenere il tempo della CPU , puoi prendere in considerazione l'utilizzo della funzione di getrusage .

Raccomando anche gli strumenti offerti da Boost. O il citato Boost Timer, o hackerare qualcosa da Boost.DateTime o c’è una nuova libreria proposta nella sandbox – Boost.Chrono : Quest’ultima sarà una sostituzione per il Timer e presenterà:

  • Le utilità temporali della libreria standard C ++ 0x, tra cui:
    • duration modello di class
    • Modello di class time_point
    • orologi:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • timer template di class, con typedefs:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • Process clock e timer:
    • process_clock , catturando i tempi reali, della CPU utente e della CPU di sistema.
    • process_timer , cattura tempi reali, CPU utente e CPU di sistema.
    • run_timer , comoda segnalazione di | process_timer | risultati.
  • L’aritmetica razionale di compilazione della libreria standard C ++ 0x.

Ecco la fonte dell’elenco delle caratteristiche

Ho scritto una class di Timer basata sulla risposta di CTT . Può essere utilizzato nel modo seguente:

 Timer timer = Timer(); timer.start(); /* perform task */ double duration = timer.stop(); timer.printTime(duration); 

Ecco la sua implementazione:

 #include  #include  #include  using namespace std; class Timer { private: timeval startTime; public: void start(){ gettimeofday(&startTime, NULL); } double stop(){ timeval endTime; long seconds, useconds; double duration; gettimeofday(&endTime, NULL); seconds = endTime.tv_sec - startTime.tv_sec; useconds = endTime.tv_usec - startTime.tv_usec; duration = seconds + useconds/1000000.0; return duration; } static void printTime(double duration){ printf("%5.6f seconds\n", duration); } }; 

Se non hai bisogno che il codice sia trasferibile ai vecchi unic, puoi usare clock_gettime (), che ti darà il tempo in nanosecondi (se il tuo processore supporta tale risoluzione). È POSIX, ma dal 2001.

clock () ha una risoluzione spesso pessima. Se vuoi misurare il tempo al millisecondo, un’alternativa è usare clock_gettime (), come spiegato in questa domanda.

(Ricorda che devi collegarti con -lrt su Linux).

Con C ++ 11 e std::chrono::high_resolution_clock puoi farlo:

 #include  #include  #include  typedef std::chrono::high_resolution_clock Clock; int main() { std::chrono::milliseconds three_milliseconds{3}; auto t1 = Clock::now(); std::this_thread::sleep_for(three_milliseconds); auto t2 = Clock::now(); std::cout < < "Delta t2-t1: " << std::chrono::duration_cast(t2 - t1).count() < < " milliseconds" << std::endl; } 

Produzione:

 Delta t2-t1: 3 milliseconds 

Link alla demo: http://cpp.sh/2zdtu

clock () non restituisce millisecondi o secondi su linux. Di solito clock () restituisce microsecondi su un sistema Linux. Il modo corretto di interpretare il valore restituito da clock () è dividerlo per CLOCKS_PER_SEC per capire quanto tempo è passato.

Questo dovrebbe funzionare … testato su un mac …

 #include  #include  int main() { struct timeval tv; struct timezone tz; struct tm *tm; gettimeofday(&tv,&tz); tm=localtime(&tv.tv_sec); printf("StartTime: %d:%02d:%02d %d \n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec); } 

Sì … eseguilo due volte e sottrai …

Nell’orologio standard POSIX il suo valore di ritorno è definito in termini del simbolo CLOCKS_PER_SEC e un’implementazione è libera di definirlo in qualsiasi modo conveniente. Sotto Linux, ho avuto fortuna con la funzione times() .

gettimeofday – il problema è che può avere valori più bassi se si cambia l’orologio hardware (con NTP per esempio) Boost – non disponibile per questo clock di progetto () – di solito restituisce un intero di 4 byte, che significa che è a bassa capacità, e dopo qualche tempo restituisce numeri negativi.

Preferisco creare la mia class e aggiornare ogni 10 millisecondi, quindi in questo modo è più flessibile e posso persino migliorarlo per avere abbonati.

 class MyAlarm { static int64_t tiempo; static bool running; public: static int64_t getTime() {return tiempo;}; static void callback( int sig){ if(running){ tiempo+=10L; } } static void run(){ running = true;} }; int64_t MyAlarm::tiempo = 0L; bool MyAlarm::running = false; 

per rinfrescarlo io uso setitimer:

 int main(){ struct sigaction sa; struct itimerval timer; MyAlarm::run(); memset (&sa, 0, sizeof (sa)); sa.sa_handler = &MyAlarm::callback; sigaction (SIGALRM, &sa, NULL); timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 10000; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 10000; setitimer (ITIMER_REAL, &timer, NULL); ..... 

Guarda setitimer e ITIMER_VIRTUAL e ITIMER_REAL.

Non utilizzare le funzioni di allarme o di allarme, si avrà una bassa precisione quando il processo diventa duro.

Preferisco la libreria Boost Timer per la sua semplicità, ma se non si desidera utilizzare librerie di terze parti, l’uso di clock () sembra ragionevole.

Come aggiornamento, appare che su windows clock () misura l’ora dell’orologio a muro (con precisione CLOCKS_PER_SEC)

  http://msdn.microsoft.com/en-us/library/4e2ess30(VS.71).aspx 

mentre su Linux misura il tempo di cpu attraverso i core utilizzati dal processo corrente

 http://www.manpagez.com/man/3/clock 

e (appare, e come notato dal poster originale) in realtà con meno precisione di CLOCKS_PER_SEC, anche se forse ciò dipende dalla specifica versione di Linux.

Mi piace il metodo Hola Soy di non usare gettimeofday (). È successo a me su un server in esecuzione l’amministratore ha cambiato il fuso orario. L’orologio è stato aggiornato per mostrare lo stesso valore (corretto) locale. Ciò ha causato il tempo di funzionamento () e gettimeofday () per spostare 2 ore e tutti i timestamp in alcuni servizi si sono bloccati.

Ho scritto una class C++ usando timeb .

 #include  class msTimer { public: msTimer(); void restart(); float elapsedMs(); private: timeb t_start; }; 

Funzioni membro:

 msTimer::msTimer() { restart(); } void msTimer::restart() { ftime(&t_start); } float msTimer::elapsedMs() { timeb t_now; ftime(&t_now); return (float)(t_now.time - t_start.time) * 1000.0f + (float)(t_now.millitm - t_start.millitm); } 

Esempio di utilizzo:

 #include  #include  using namespace std; int main(int argc, char** argv) { msTimer t; for (int i = 0; i < 5000000; i++) ; std::cout << t.elapsedMs() << endl; return 0; } 

L'output sul mio computer è '19'. La precisione della class msTimer è dell'ordine di millisecondi. Nell'esempio di utilizzo di cui sopra, viene tracciato il tempo totale di esecuzione occupato da for -loop. Questa volta ha incluso il sistema operativo che triggers e distriggers il contesto di esecuzione di main() causa del multitasking.