C++ obtenir des millisecondes de temps sur Linux - clock () ne semble pas fonctionner correctement

sur Windows, clock() renvoie le temps en millisecondes, mais sur cette machine Linux sur laquelle je travaille, elle tourne au 1000 le plus proche donc la précision est seulement au niveau" second " et pas au niveau millisecondes.

j'ai trouvé une solution avec Qt à l'aide de la QTime la classe, l'instanciation d'un objet et en l'appelant start() sur elle, puis de l'appel elapsed() pour obtenir le nombre de millisecondes écoulées.

j'ai eu un peu de chance parce que je suis travailler avec Qt pour commencer, mais je voudrais une solution qui ne repose pas sur des bibliothèques tierces", 151950920"

N'y a-t-il pas de méthode standard pour faire cela?

mise à JOUR

s'il vous Plaît ne recommandent pas de coup de pouce ..

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

97
demandé sur Jonathan Leffler 2009-02-26 01:59:29

16 réponses

, Vous pouvez utiliser gettimeofday au début et à la fin de votre méthode, puis la différence les deux structures. Vous obtiendrez la structure suivante:

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}
35
répondu Adam Hawes 2009-02-25 23:12:25
#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
répondu CTT 2009-02-25 23:20:24

s'il vous Plaît noter que clock ne pas mesurer le temps 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 donc pourrait consommer plus de CPU que le temps réel) ou moins. Il mesure une approximation de temps CPU utilisé. Pour voir la différence, considérez 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;
}

sorties It sur mon système

$ difference: 0

parce que tout ce que nous avons fait c'était dormir et ne pas utiliser de temps CPU! 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 CPU time , alors vous pouvez envisager d'utiliser la fonction getrusage .

57
répondu Johannes Schaub - litb 2011-01-03 07:49:26

je recommande également les outils offerts par Boost. Soit le Boost Timer mentionné, soit pirater quelque chose de Boost.DateTime ou il ya une nouvelle bibliothèque proposée dans le bac à sable - Boost.Chrono : ce dernier remplacera la minuterie et comprendra:

  • Le C++0x Bibliothèque Standard du temps d'utilitaires, 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 typographies:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • processus horloges et minuteries:
    • process_clock , la capture réel, l'utilisateur de la CPU, et le système de temps de calcul.
    • process_timer , capture de temps réel, temps utilisateur-CPU, et Temps Système-CPU.
    • run_timer , pratique de rapports de |process_timer| résultats.
  • Le C++0x Standard de la Bibliothèque au moment de la compilation rationnelle de l'arithmétique.

Voici la source de la liste des caractéristiques

18
répondu Anonymous 2009-02-25 23:33:34

j'ai écrit une classe Timer basée sur la 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 œuvre:

#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
répondu Chris Redford 2017-05-23 12:26:22

si vous n'avez pas besoin que le code soit portable à de vieilles unités, vous pouvez utiliser clock_gettime(), qui vous donnera l'heure en nanosecondes (si votre processeur supporte cette résolution). C'est POSIX, mais à partir de 2001.

9
répondu Zachary Hamm 2009-02-26 03:17:26

horloge () a une résolution souvent assez moche. Si vous voulez mesurer le temps au niveau milliseconde, une alternative est d'utiliser clock_gettime(), comme expliqué dans cette question.

(rappelez-vous que vous devez vous connecter avec-lrt sous Linux).

4
répondu JesperE 2017-05-23 12:18:17

avec C++11 et std::chrono::high_resolution_clock vous pouvez faire ceci:

#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/2zdtu

3
répondu Martin G 2016-06-07 08:21:25

clock () ne renvoie ni millisecondes ni secondes sur linux. En général clock () retourne des microsecondes sur un système linux. La bonne façon d'interpréter la valeur retournée par Clocks() est de la diviser par CLOCKS_PER_SEC pour déterminer combien de temps s'est écoulé.

2
répondu SoapBox 2009-02-25 23:07:12

ça devrait marcher...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);
}

Oui...exécutez deux fois et soustraire...

1
répondu Jason Punyon 2009-02-25 23:18:51

dans la norme POSIX clock a sa valeur de retour définie en termes du symbole CLOCKS_PER_SEC et une implémentation est libre de définir cela de n'importe quelle manière commode. Sous Linux, j'ai eu de la chance avec la fonction times() .

1
répondu Jon Trauntvein 2010-05-04 17:42:08

gettimeofday - le problème est que will peut avoir des valeurs inférieures si vous changez votre horloge matérielle (avec NTP par exemple) Boost - non disponible pour ce projet clock () - renvoie habituellement un entier de 4 octets, ce qui signifie que sa capacité est faible, 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, donc cette façon est 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 ITIMER_VIRTUAL et ITIMER_REAL.

N'utilisez pas l'alarme ou les fonctions ualarm, vous aurez une faible précision lorsque votre processus obtenir un travail difficile.

1
répondu Hola Soy Edu Feliz Navidad 2012-09-04 12:25:45

je préfère la Boost Timer library pour sa simplicité, mais si vous ne voulez pas utiliser les bibliothèques third-parrty, utiliser clock() semble raisonnable.

0
répondu Nick Presta 2009-02-25 23:18:35

comme mise à jour,apparaît que sur Windows clock() mesure l'Heure de l'horloge murale (avec précision CLOCKS_PER_SEC)

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

alors que sur Linux il mesure le temps cpu à travers les cœurs utilisés par le processus actuel

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

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

0
répondu rogerdpack 2010-08-11 14:29:40

j'aime le Hola Soy méthode de ne pas utiliser gettimeofday(). Il m'est arrivé sur un serveur exécutant l'admin changé le fuseau horaire. L'horloge a été mise à jour pour afficher la même valeur locale (correcte). Cela a provoqué la fonction time() et gettimeofday () à décaler de 2 heures et tous les horodateurs dans certains services ont été bloqués.

0
répondu gkolarov 2014-10-09 12:27:33

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 de membre:

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

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

0
répondu user3674642 2016-01-23 04:04:28