web-dev-qa-db-fra.com

Obtenir du temps C ++ en millisecondes sous Linux - clock () ne semble pas fonctionner correctement

Sous Windows, clock() renvoie le temps en millisecondes, mais sur cette machine Linux sur laquelle je travaille, il est arrondi au millier le plus proche. La précision est donc au "deuxième" niveau et non aux millisecondes. niveau.

J'ai trouvé une solution avec Qt en utilisant la classe QTime, en instanciant un objet et en appelant start() puis en appelant elapsed() pour obtenir le nombre de millisecondes écoulées.

J'ai eu un peu de chance parce que je travaille avec Qt pour commencer, mais j'aimerais une solution qui ne repose pas sur des bibliothèques tierces,

N'y a-t-il aucun moyen standard de faire cela?

MISE À JOUR

S'il vous plaît ne recommande pas Boost ..

Si Boost et Qt peuvent le faire, ce n'est sûrement pas magique, il doit y avoir quelque chose de standard qu'ils utilisent!

97
hasen

Vous pouvez utiliser gettimeofday au début et à la fin de votre méthode, puis différencier les deux structures de retour. Vous obtiendrez une structure comme celle-ci:

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}
36
Adam Hawes
#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;
}
137
CTT

Veuillez noter que clock ne pas mesure l'heure de l'horloge murale. Cela signifie que si votre programme prend 5 secondes, clock ne mesurera pas nécessairement 5 secondes, mais pourrait en faire plus (votre programme pourrait exécuter plusieurs threads et pourrait donc consommer plus de CPU que de temps réel) ou moins. Il mesure une approximation de temps de calcul utilisé. Pour voir la différence, considérons ce code

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

Il sort sur mon système

$ difference: 0

Parce que tout ce que nous faisions était dormir et ne pas utiliser de temps processeur! Cependant, en utilisant gettimeofday nous obtenons ce que nous voulons (?)

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

Sorties sur mon système

$ difference: 5

Si vous avez besoin de plus de précision mais que vous voulez obtenir temps de calcul, vous pouvez envisager d'utiliser la fonction getrusage.

57

Je recommande également les outils proposés par Boost. Soit le minuteur Boost mentionné, soit piratez quelque chose hors de Boost.DateTime ou il y a une nouvelle bibliothèque proposée dans le bac à sable - Boost.Chrono : Ce dernier remplacera le minuteur et comportera:

  • Utilitaires de temps de la bibliothèque standard C++ 0x, y compris:
    • Modèle de classe duration
    • Modèle de classe time_point
    • Horloges:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • Modèle de classe timer, avec typedefs:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • Traitement des horloges et des minuteries:
    • process_clock, en capturant les temps réels, CPU utilisateur et système.
    • process_timer, capture des temps réels écoulés, de la CPU utilisateur et des temps système.
    • run_timer, rapports pratiques de | process_timer | résultats.
  • Arithmétique rationnelle au moment de la compilation de la bibliothèque standard C++ 0x.

Voici la source de la liste des fonctionnalités

18
Anonymous

J'ai écrit une classe Timer basée sur réponse de CTT . Il peut être utilisé de la manière suivante:

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

Voici sa mise en oeuvre:

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

Si vous n'avez pas besoin que le code soit portable sur les anciens ordinateurs, vous pouvez utiliser clock_gettime (), qui vous donnera l'heure en nanosecondes (si votre processeur prend en charge cette résolution). C'est POSIX, mais à partir de 2001.

9
Zachary Hamm

clock () a une résolution souvent moche. Si vous voulez mesurer le temps au niveau de la milliseconde, une solution consiste à utiliser clock_gettime (), comme expliqué dans cette question.

(N'oubliez pas que vous devez créer un lien avec -lrt sous Linux).

4
JesperE

Avec C++ 11 et std::chrono::high_resolution_clock tu peux le faire:

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

Sortie:

Delta t2-t1: 3 milliseconds

Lien vers la démo: http://cpp.sh/2zdt

3
Martin G

clock () ne renvoie pas des millisecondes ou des secondes sous Linux. Généralement, clock () renvoie des microsecondes sur un système Linux. La bonne façon d'interpréter la valeur renvoyée par clock () consiste à la diviser par CLOCKS_PER_SEC pour déterminer le temps écoulé.

2
SoapBox

Dans le standard POSIX, clock a sa valeur de retour définie en fonction du symbole CLOCKS_PER_SEC et une implémentation est libre de le définir de manière appropriée. Sous Linux, j'ai eu de la chance avec la fonction times().

1
Jon Trauntvein

gettimeofday - le problème est que vous pouvez avoir des valeurs plus basses si vous modifiez votre horloge matérielle (avec NTP par exemple) Boost - non disponible pour cette horloge de projet () - renvoie généralement un entier de 4 octets, ce qui signifie que c'est une faible capacité, et après un certain temps, il renvoie des nombres négatifs.

Je préfère créer ma propre classe et mettre à jour toutes les 10 millisecondes. Cette méthode est donc plus flexible et je peux même l'améliorer pour avoir des abonnés.

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;

pour le rafraîchir, j'utilise 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); 
.....

Regardez setitimer et les variables ITIMER_VIRTUAL et ITIMER_REAL.

N'utilisez pas les fonctions alarm ou ualarm, vous aurez une faible précision lorsque vos processus auront du travail.

Cela devrait fonctionner ... testé sur 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);
}

Ouais ... lancez-le deux fois et soustrayez ...

1
Jason Punyon

J'aime la méthode Hola Soy qui consiste à ne pas utiliser gettimeofday (). Il m'est arrivé sur un serveur en cours d'exécution, l'administrateur a modifié le fuseau horaire. L'horloge a été mise à jour pour afficher la même valeur locale (correcte). La fonction time () et gettimeofday () changeaient donc de 2 heures et tous les horodatages de certains services étaient bloqués.

0
gkolarov

En guise de mise à jour, il apparaît que windows clock () mesure l'heure de l'horloge murale (avec la précision CLOCKS_PER_SEC)

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

tandis que sur Linux, il mesure le temps processeur à travers les cœurs utilisés par les processus actuels

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

et (il semble, et comme indiqué par l'affiche originale) en réalité avec moins précision que CLOCKS_PER_SEC, bien que cela dépend peut-être de la version spécifique de Linux.

0
rogerdpack

Je préfère la bibliothèque Boost Timer pour sa simplicité, mais si vous ne voulez pas utiliser les bibliothèques de troisième copie, utiliser clock () semble raisonnable.

0
Nick Presta

J'ai écrit une classe C++ En utilisant timeb.

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

Fonctions membres:

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

Exemple d'utilisation:

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

La sortie sur mon ordinateur est '19'. La précision de la classe msTimer est de l'ordre de quelques millisecondes. Dans l'exemple d'utilisation ci-dessus, le temps total d'exécution pris par la boucle for- est suivi. Cette fois-ci, le système d’exploitation a basculé dans le contexte d’exécution de main() en raison du multitâche.

0
user3674642