web-dev-qa-db-fra.com

Mesurer le temps sous Linux: heure vs horloge vs getrusage vs horloge_gettime vs gettimeofday vs timespec_get?

Parmi les fonctions de minutage, time, clockgetrusage, clock_gettime, gettimeofday et timespec_get, Je veux comprendre clairement comment elles sont mises en œuvre et quelles sont leurs valeurs de retour afin de savoir dans quelle situation je dois les utiliser.

Nous devons d’abord classer les fonctions retournant valeurs de wall-clock par rapport aux fonctions retournant valeurs de processus ou de threads. gettimeofday renvoie la valeur de l'horloge murale, clock_gettime renvoie la valeur de l'horloge murale o les valeurs de processus ou de threads en fonction du paramètre Clock qui lui a été transmis. getrusage et clock renvoient des valeurs de processus.

Ensuite, la deuxième question concerne la mise en œuvre de ces fonctions et, par conséquent, leur précision. Quel mécanisme matériel ou logiciel ces fonctions utilisent-elles.

Il semble que getrusage utilise uniquement le tick du noyau (généralement 1 ms) et ne peut donc pas être plus précis que le ms. Est ce bien? Ensuite, la fonction getimeofday semble utiliser le matériel sous-jacent le plus précis disponible. En conséquence, sa précision est généralement de l'ordre de la microseconde (ne peut pas être plus en raison de l'API) sur du matériel récent. Qu'en est-il de clock, la page de manuel parle d’approximation, que signifie-t-elle? Qu'en est-il de clock_gettime, l’API est en nanosecondes. Cela signifie-t-il qu’elle peut être aussi précise si le matériel sous-jacent le permet? Qu'en est-il de la monotonie?

Y a-t-il d'autres fonctions?

137
Manuel Selva

Le problème est qu’il existe plusieurs fonctions de temps disponibles en C et C++, et que certaines d’entre elles présentent des comportements différents selon les implémentations. Il y a aussi beaucoup de demi-réponses qui circulent. La compilation d'une liste de fonctions d'horloge avec leurs propriétés répondrait correctement à la question. Pour commencer, demandons quelles sont les propriétés pertinentes que nous recherchons. En regardant votre post, je suggère:

  • Quelle heure est mesurée par l'horloge? (réel, utilisateur, système ou, espérons-le, non, horloge murale?)
  • Quelle est la précision de l'horloge? (s, ms, µs ou plus rapide?)
  • Après combien de temps l'horloge tourne-t-elle? Ou existe-t-il un mécanisme pour éviter cela?
  • L'horloge est-elle monotone ou changera-t-elle avec les modifications de l'heure du système (via NTP, le fuseau horaire, l'heure d'été, par l'utilisateur, etc.)?
  • Comment les éléments ci-dessus varient-ils entre les mises en œuvre?
  • La fonction spécifique est-elle obsolète, non standard, etc.?

Avant de commencer la liste, je voudrais souligner que l’horloge murale est rarement le bon moment, alors qu’elle change en fonction des changements de fuseau horaire, de l’heure avancée ou si l’horloge murale est synchronisée par NTP. Aucune de ces choses sont bonnes si vous utilisez le temps nécessaire pour planifier des événements ou pour évaluer les performances. Ce n'est que vraiment bon pour ce que le nom dit, une horloge sur le mur (ou le bureau).

Voici ce que j'ai trouvé jusqu'à présent pour les horloges sous Linux et OS X:

  • time() renvoie l'heure de l'horloge murale à partir du système d'exploitation, avec une précision en secondes.
  • clock() semble renvoyer la somme de l'heure utilisateur et de l'heure système. Il est présent dans C89 et plus tard. À un moment donné, ce temps était censé représenter le temps de calcul par cycle, mais les normes modernes comme POSIX exigent que CLOCKS_PER_SEC soit égal à 1000000, ce qui donne une précision maximale possible de 1 µs. La précision sur mon système est en effet de 1 µs. Cette horloge tourne autour une fois qu’elle dépasse (cela se produit généralement après environ 2 ^ 32 ticks, ce qui n’est pas très long pour une horloge de 1 MHz). man clock Indique que depuis la glibc 2.18, il est implémenté avec clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) sous Linux.
  • clock_gettime(CLOCK_MONOTONIC, ...) fournit une résolution en nanosecondes, est monotone. Je crois que les "secondes" et les "nanosecondes" sont stockées séparément, chacune dans des compteurs 32 bits. Ainsi, tout bouclage se produirait après plusieurs dizaines d’années de disponibilité. Cela ressemble à une très bonne horloge, mais malheureusement, il n’est pas encore disponible sur OS X. POSIX 7 décrit CLOCK_MONOTONIC Comme une extension facultative .
  • getrusage() s'est avéré être le meilleur choix pour ma situation. Il signale les heures de l'utilisateur et du système séparément et ne fait pas le tour. La précision sur mon système est de 1 µs, mais je l’ai également testée sur un système Linux (Red Hat 4.1.2-48 avec GCC 4.1.2) et la précision n’était que de 1 ms.
  • gettimeofday() renvoie l'heure de l'horloge murale avec une précision (nominale) µs. Sur mon système, cette horloge semble avoir une précision de µs, mais cela n’est pas garanti, car "la résolution de l’horloge système dépend du matériel" . POSIX.1-2008 dit que . "Les applications doivent utiliser la fonction clock_gettime() au lieu de la fonction obsolète gettimeofday()", vous devez donc vous en tenir éloigné. Linux x86 et l'implémente en tant qu'appel système .
  • mach_absolute_time() est une option permettant une synchronisation très haute résolution (ns) sous OS X. Sur mon système, cela donne bien une résolution de ns. En principe, cette horloge est enveloppante, mais elle stocke ns en utilisant un entier non signé de 64 bits, de sorte que l'encapsulation ne devrait pas être un problème en pratique. La portabilité est discutable.
  • J'ai écrit une fonction hybride basé sur cet extrait qui utilise clock_gettime lorsqu'il est compilé sous Linux, ou un compteur de temps mécanique lorsqu'il est compilé sous OS X, afin d'obtenir une précision ns sous Linux et OS X.

Tout ce qui précède existe sous Linux et OS X, sauf indication contraire. "Mon système" dans ce qui précède est un Apple sous OS X 10.8.3 avec GCC 4.7.2 de MacPorts.

Enfin, voici une liste de références que j'ai trouvées utiles en plus des liens ci-dessus:


Mise à jour : pour OS X, clock_gettime A été implémenté à partir de 10.12 (Sierra). De plus, les plates-formes POSIX et BSD (comme OS X) partagent le champ struct rusage.ru_utime.

183
Douglas B. Staple

C11 timespec_get

Exemple d'utilisation à l'adresse suivante: https://stackoverflow.com/a/36095407/895245

La précision maximale possible renvoyée est de nanosecondes, mais la précision réelle est définie par la mise en œuvre et peut être inférieure.

Il retourne l'heure du mur, pas l'utilisation du processeur.

la glibc 2.21 l'implémente sous sysdeps/posix/timespec_get.c et est transmise directement à:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettime Et CLOCK_REALTIME Sont POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html , et man clock_gettime Indique que cette mesure peut avoir des discontinuités si vous modifiez un réglage de l'heure du système pendant l'exécution de votre programme.

C++ 11 chrono

Puisque nous y sommes, couvrons-les également: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C++ stdlib est à l'intérieur de la source GCC):

  • high_resolution_clock est un alias pour system_clock
  • system_clock transmet au premier des éléments suivants qui sont disponibles:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock transmet au premier des éléments suivants qui sont disponibles:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

Question posée à: Différence entre std :: system_clock et std :: steady_clock?

CLOCK_REALTIME Vs CLOCK_MONOTONIC: Différence entre CLOCK_REALTIME et CLOCK_MONOTONIC?