C ++ ottenendo tempo millisecondi su Linux - orologio () non sembra funzionare correttamente

StackOverflow https://stackoverflow.com/questions/588307

  •  09-09-2019
  •  | 
  •  

Domanda

In Windows, clock() restituisce il tempo in millisecondi, ma su questo Linux su cui sto lavorando, si arrotonda al più vicino 1000 così la precisione è solo al livello "secondo" e non al livello di millisecondi.

Ho trovato una soluzione con Qt utilizzando la classe QTime, istanziare un oggetto e chiamando start() su di esso quindi chiamando elapsed() per ottenere il numero di millisecondi trascorsi.

ho avuto tipo di fortunato perché sto lavorando con Qt per cominciare, ma mi piacerebbe una soluzione che non si basa su librerie di terze parti,

Non c'è un modo standard per fare questo?

Aggiorna

Si prega di non raccomandare Boost ..

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

È stato utile?

Soluzione

È possibile utilizzare gettimeofday all'inizio e alla fine del tuo metodo e poi di differenza le due struct ritorno. Si otterrà una struttura come il seguente:

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}

Altri suggerimenti

#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
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 clock non misura muro ora dell'orologio. Ciò significa che se il vostro programma impiega 5 secondi, clock non misurerà 5 secondi necessariamente, ma potrebbe più (il programma potrebbe eseguire più thread e così potrebbe consumare di più CPU rispetto al tempo reale) o meno. Esso misura un'approssimazione di il tempo di CPU utilizzato. Per vedere la differenza in considerazione questo codice

#include <iostream>
#include <ctime>
#include <unistd.h>

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;
}

E 'uscite sul mio sistema

$ difference: 0

Perché tutti abbiamo stava dormendo e che non utilizzano alcun tempo di CPU! Tuttavia, utilizzando gettimeofday otteniamo quello che vogliamo (?)

#include <iostream>
#include <ctime>
#include <unistd.h>
#include <sys/time.h>

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;
}

Le uscite sul mio sistema

$ difference: 5

Se avete bisogno di più precisione, ma vuole ottenere il tempo di CPU , allora si può considerare l'uso della funzione di getrusage.

Raccomando anche gli strumenti offerti dalla Boost. O il Timer Boost citato, o hack qualcosa di Boost.DateTime o v'è nuova biblioteca proposto nella sandbox - Boost.Chrono : Questo ultimo sarà un sostituto per il timer e sarà caratterizzato da:

  • Utility per sempre I ++ 0x standard di libreria C, tra cui:
    • modello Classe duration
    • modello Classe time_point
    • Orologi:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • modello Classe timer, con typedef:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • orologi e timer di processo:
    • process_clock, catturando reale, user-CPU, ed il sistema-CPU volte.
    • process_timer, catturando trascorso reale, user-CPU, ed il sistema-CPU volte.
    • run_timer, conveniente segnalazione di | process_timer | risultati.
  • in fase di compilazione aritmetica razionale del 0x libreria standard C ++.

Ecco la fonte della lista delle caratteristiche

Ho scritto una classe Timer basata su del CTT risposta . Può essere utilizzato nel seguente modo:

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

Ecco la sua attuazione:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
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 è necessario il codice per essere portabile su vecchi sistemi Unix, è possibile utilizzare clock_gettime (), che vi darà il tempo di nanosecondi (se il vostro processore supporta tale risoluzione). E 'POSIX, ma a partire dal 2001.

clock () ha una risoluzione spesso piuttosto scadente. Se si vuole misurare il tempo a livello di millisecondo, un'alternativa è quella di utilizzare clock_gettime (), come ha spiegato in questa domanda.

(Ricordate che è necessario per il collegamento con -lrt su Linux).

Con C ++ 11 e std::chrono::high_resolution_clock si può fare questo:

#include <iostream>
#include <chrono>
#include <thread>
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<std::chrono::milliseconds>(t2 - t1).count()
              << " milliseconds" << std::endl;
}

Output:

Delta t2-t1: 3 milliseconds

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

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

Questo dovrebbe funzionare ... testato su un mac ...

#include <stdio.h>
#include <sys/time.h>

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);
}

Si ... giocarla due volte e sottrarre ...

Nel clock standard POSIX ha il valore restituito definito in termini di simbolo CLOCKS_PER_SEC e un'implementazione è libero di definire questo in qualsiasi modo conveniente. Sotto Linux, ho avuto fortuna con la funzione times().

gettimeofday - il problema è che la volontà può avere valori più bassi se si si cambia orologio hardware (con NTP per esempio) Boost - non disponibile per questo progetto clock () -. solitamente restituisce un numero intero di 4 byte, wich significa che la sua capacità bassa, e dopo qualche tempo restituisce numeri negativi

Io preferisco creare la mia classe e aggiornare ogni 10 millisecondi, così in questo modo è più flessibile, e posso anche migliorarlo 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 aggiornarlo 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 l'ITIMER_VIRTUAL e ITIMER_REAL.

Non utilizzare le funzioni di allarme o ualarm, si avrà scarsa precisione quando il processo di ottenere un duro lavoro.

Io preferisco il rel="nofollow Boost Timer biblioteca la sua semplicità, ma se non si desidera utilizzare librerie di terze parrty, utilizzando orologio () sembra ragionevole.

Come un aggiornamento, sembra che sulle finestre di clock () misura il tempo orologio da parete (con CLOCKS_PER_SEC precisione)

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

mentre su Linux che misura il tempo di CPU attraverso nuclei utilizzate dal processo in corso

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

e (a quanto pare, e come ha fatto notare il manifesto originale) in realtà con meno precisione rispetto CLOCKS_PER_SEC, anche se forse questo dipende dalla specifica versione di Linux.

Mi piace il metodo Hola Soy di non utilizzare gettimeofday (). E 'successo a me su un server che esegue l'amministratore ha cambiato il fuso orario. L'orologio è stato aggiornato per mostrare la stessa (corretto) valore locale. Ciò ha causato la funzione time () e gettimeofday () per spostare 2 ore e tutti i timestamp in alcuni servizi è rimasto bloccato.

ho scritto una classe C++ utilizzando timeb.

#include <sys/timeb.h>
class msTimer 
{
public:
    msTimer();
    void restart();
    float elapsedMs();
private:
    timeb t_start;
};

Le 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 <cstdlib>
#include <iostream>

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;
}

Uscita sul mio computer è '19'. La precisione della classe msTimer è dell'ordine di millisecondi. Nell'esempio di utilizzo sopra, il tempo totale di esecuzione occupata dal for-loop è monitorato. Questa volta incluso il sistema operativo di commutazione e il contesto di esecuzione di main() causa di multitasking.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top