C ++ zu erhalten Millisekunden Zeit auf Linux - clock () scheint nicht richtig funktioniert

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

  •  09-09-2019
  •  | 
  •  

Frage

Unter Windows clock() die Zeit in Millisekunden zurück, aber auf dieser Linux-Box arbeite ich an, es rundet es auf die nächsten 1000 so ist die Präzision nur auf die „zweite“ Ebene und nicht auf die Millisekunden-Ebene.

ich eine Lösung mit Qt mit der QTime Klasse gefunden, ein Objekt zu erhalten und forderte sie auf, start() dann elapsed() ruft die Anzahl der Millisekunden zu erhalten verstrichen ist.

Ich habe Art von Glück, weil ich mit Qt bin mit zu beginnen, aber ich würde eine solche Lösung, die nicht auf Bibliotheken von Drittanbietern angewiesen ist,

Gibt es keinen Standard-Weg, dies zu tun?

UPDATE

Bitte-Boost nicht empfehlen ..

Wenn Boost und Qt es tun kann, sicher ist es nicht Magie, da Standard etwas sein muss, dass sie verwenden!

War es hilfreich?

Lösung

Sie könnten am Anfang und Ende Ihrer Methode verwenden gettimeofday und dann Differenz der beiden Rück structs. Sie erhalten eine Struktur wie folgt erhalten:

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}

Andere Tipps

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

Bitte beachten Sie, dass clock tut nicht Maß Wanduhr Zeit. Das bedeutet, wenn Ihr Programm 5 Sekunden dauert, clock misst 5 Sekunden nicht unbedingt, aber könnte mehr (Ihr Programm könnte mehrere Threads laufen und so mehr CPU als in Echtzeit verbrauchen könnte) oder weniger. Er misst eine Annäherung von CPU-Zeit verwendet. Um zu sehen, die Differenz diesen Code betrachten

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

Es gibt auf meinem System

$ difference: 0

Weil alles, was wir haben geschlafen und keine CPU-Zeit! Doch mit gettimeofday wir bekommen, was wir wollen (?)

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

Ausgänge auf meinem System

$ difference: 5

Wenn Sie mehr Präzision benötigen, wollen aber bekommen CPU-Zeit , dann können Sie betrachten die getrusage Funktion.

Ich empfehle auch die Werkzeuge von Boost angeboten. Entweder ist der erwähnte Boost-Timer oder hackt etwas aus Boost.DateTime oder gibt es neue vorgeschlagene Bibliothek in der Sandbox - Boost.Chrono : das letzte wird einen Ersatz für die Timer und wird Feature:

  • Der C ++ 0x Standard Library Zeit Dienstprogramme, einschließlich:
    • Klasse template duration
    • Klasse template time_point
    • Uhren:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • Vorlage Klasse timer, mit typedefs:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • Prozess Uhren und Timer:
    • process_clock, Capturing real, Benutzer-CPU und System-CPU-Zeiten.
    • process_timer, Capturing verstrichene real, Benutzer-CPU und System-CPU-Zeiten.
    • run_timer, bequem Meldung von | process_timer | Ergebnisse.
  • Der C ++ 0x Standard Library des Kompilierung-rationale Arithmetik.

Hier ist die Quelle der Feature-Liste

Ich habe eine Timer Klasse geschrieben, basierend auf Antwort des CTT. Es kann auf folgende Weise verwendet werden:

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

Hier ist seine Umsetzung:

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

Wenn Sie den Code nicht benötigen, um alte Unix-Varianten tragbar zu sein, Sie clock_gettime () verwenden können, die Sie in die Zeit geben ns (wenn Ihr Prozessor unterstützt diese Auflösung). Es ist POSIX, aber von 2001.

clock () hat eine oft eine ziemlich miese Auflösung. Wenn Sie Zeit im Millisekunden-Ebene messen wollen, eine Alternative ist clock_gettime () zu verwenden, wie erklärt in dieser Frage.

(Denken Sie daran, dass Sie mit -lrt auf Linux verbinden müssen).

Mit C ++ 11 und std::chrono::high_resolution_clock Sie dies tun können:

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

Ausgabe:

Delta t2-t1: 3 milliseconds

Link zur Demo: http://cpp.sh/2zdtu

clock () nicht zurückgibt Millisekunden oder Sekunden auf Linux. Normalerweise Uhr () gibt Mikrosekunden auf einem Linux-System. Der richtige Weg, um den Wert von clock () ist dividieren sie durch CLOCKS_PER_SEC um herauszufinden, wie viel Zeit vergangen ist.

zurück zu interpretieren

Dies sollte ... auf einem Mac getestet ...

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

Ja ... führen Sie es zweimal und subtrahieren ...

In der POSIX-Standard clock hat der Rückgabewert definiert in Bezug auf die CLOCKS_PER_SEC Symbol und eine Implementierung ist frei, diese in jeder geeigneten Art und Weise zu definieren. Unter Linux habe ich viel Glück mit der times() Funktion hatte.

gettimeofday - das Problem ist, dass niedrigere Werte haben kann, wenn Sie Ihnen Hardware-Uhr ändern (mit NTP zum Beispiel) Steigern Sie - nicht für dieses Projekt zur Verfügung (Takt) -. In der Regel gibt eine 4 Byte ganze Zahl ist, wich bedeutet, dass seine eine geringe Kapazität, und nach einiger Zeit gibt es negative Zahlen

Ich ziehe meine eigene Klasse zu erstellen und alle 10 Millisekunden aktualisiert werden, so dass diese Art und Weise ist flexibler, und ich kann es sogar verbessern Abonnenten zu haben.

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;

aktualisieren es verwende ich 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); 
.....

Schauen Sie sich setitimer und der ITIMER_VIRTUAL und ITIMER_REAL.

Sie die Alarm oder ualarm Funktionen nicht verwenden, werden Sie geringe Genauigkeit haben, wenn Ihr Prozess eine harte Arbeit.

ziehe ich die Timer Bibliothek Erhöhung seine Einfachheit, aber wenn Sie nicht möchten, dass Dritt parrty Bibliotheken verwenden, scheint mit Uhr () sinnvoll.

Als Update erscheint, dass auf Windows-Uhr () misst Wanduhr Zeit (mit CLOCKS_PER_SEC Präzision)

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

, während auf Linux misst CPU-Zeit über Kerne von aktuellem Prozess verwendet

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

und (wie es scheint, und wie vom Verfasser angegeben) tatsächlich mit weniger Präzision als CLOCKS_PER_SEC, aber vielleicht hängt dies von der spezifischen Version von Linux.

Ich mag die Hola Soy Methode nicht gettimeofday () verwenden. Es passiert mir auf einem laufenden Server der Administrator die Zeitzone geändert. Die Uhr wurde aktualisiert, um den gleichen (richtigen) lokalen Wert anzuzeigen. Dies verursachte die Funktion time () und gettimeofday () 2 Stunden zu verschieben und alle Zeitstempel in einigen Diensten stecken geblieben.

Ich schrieb eine C++-Klasse timeb.

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

Member-Funktionen:

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

Anwendungsbeispiel:

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

Ausgabe auf meinem Computer ist '19'. Die Genauigkeit der msTimer Klasse ist in der Größenordnung von Millisekunden. Im Anwendungsbeispiel ist die Gesamtzeit der Ausführung oben, durch die for-Schleife aufgenommen wird verfolgt. Diesmal mit dem Betriebssystem in die und aus den Ausführungskontext des main() aufgrund Multitasking Schalt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top