Zeit unter Linux messen - Zeit gegen Uhr gegen getrusage gegen clock_gettime gegen gettimeofday gegen timespec_get?

148

Zu den Zeitfunktionen, time, clock getrusage, clock_gettime, gettimeofdayund timespec_get, mag ich klar verstehen , wie sie umgesetzt werden und was sind ihre Rückgabewerte , um zu wissen , in welcher Situation ich habe sie zu nutzen.

Zuerst müssen wir Funktionen klassifizieren, die Wanduhrwerte zurückgeben , im Vergleich zu Funktionen, die Prozess- oder Threadwerte zurückgeben . gettimeofdayGibt den Wanduhrwert zurück, clock_gettimegibt den Wanduhrwert oder den Prozess- oder Threadwert zurück, abhängig von dem an ihn übergebenen ClockParameter. getrusageund clockProzesswerte zurückgeben.

Die zweite Frage betrifft dann die Implementierung dieser Funktionen und folglich ihre Genauigkeit. Welchen Hardware- oder Softwaremechanismus verwenden diese Funktionen?

Es scheint, dass getrusagenur der Kernel-Tick verwendet wird (normalerweise 1 ms lang) und daher nicht genauer als die ms sein kann. Ist es richtig? Dann getimeofdayscheint die Funktion die genaueste zugrunde liegende verfügbare Hardware zu verwenden. Infolgedessen beträgt seine Genauigkeit normalerweise die Mikrosekunde (kann aufgrund der API nicht höher sein) auf neuerer Hardware. Was ist mit clock, die Manpage spricht von "Annäherung", was bedeutet das? Was clock_gettimeist mit der API in Nanosekunden? Bedeutet dies, dass sie so genau sein kann, wenn die zugrunde liegende Hardware dies zulässt? Was ist mit Monotonie?

Gibt es noch andere Funktionen?

Manuel Selva
quelle

Antworten:

198

Das Problem ist, dass in C und C ++ verschiedene Zeitfunktionen verfügbar sind und einige von ihnen sich im Verhalten zwischen den Implementierungen unterscheiden. Es gibt auch viele halbe Antworten. Das Zusammenstellen einer Liste von Uhrfunktionen zusammen mit ihren Eigenschaften würde die Frage richtig beantworten. Lassen Sie uns zunächst fragen, nach welchen relevanten Eigenschaften wir suchen. Wenn ich mir Ihren Beitrag ansehe, schlage ich vor:

  • Welche Zeit wird von der Uhr gemessen? (Real, Benutzer, System oder hoffentlich nicht Wanduhr?)
  • Was ist die Präzision der Uhr? (s, ms, µs oder schneller?)
  • Nach wie viel Zeit dreht sich die Uhr? Oder gibt es einen Mechanismus, um dies zu vermeiden?
  • Ist die Uhr monoton oder ändert sie sich mit Änderungen der Systemzeit (über NTP, Zeitzone, Sommerzeit, vom Benutzer usw.)?
  • Wie unterscheiden sich die oben genannten Punkte zwischen den Implementierungen?
  • Ist die spezifische Funktion veraltet, nicht standardisiert usw.?

Bevor ich mit der Liste beginne, möchte ich darauf hinweisen, dass die Wanduhrzeit selten die richtige Zeit ist, während sie sich mit Änderungen der Zeitzone, der Sommerzeit oder der Synchronisierung der Wanduhr durch NTP ändert. Keines dieser Dinge ist gut, wenn Sie die Zeit nutzen, um Ereignisse zu planen oder die Leistung zu bewerten. Es ist nur wirklich gut für das, was der Name sagt, eine Uhr an der Wand (oder auf dem Desktop).

Folgendes habe ich bisher für Uhren unter Linux und OS X gefunden:

  • time() Gibt die Wanduhrzeit vom Betriebssystem mit einer Genauigkeit in Sekunden zurück.
  • clock()scheint die Summe aus Benutzer- und Systemzeit zurückzugeben. Es ist in C89 und höher vorhanden. Früher sollte dies die CPU-Zeit in Zyklen sein, aber moderne Standards wie POSIX verlangen, dass CLOCKS_PER_SEC 1000000 ist, was eine maximal mögliche Genauigkeit von 1 µs ergibt. Die Genauigkeit auf meinem System beträgt in der Tat 1 µs. Dieser Takt dreht sich um, sobald er das Maximum erreicht hat (dies geschieht normalerweise nach ~ 2 ^ 32 Ticks, was für einen 1-MHz-Takt nicht sehr lang ist). man clocksagt, dass es seit glibc 2.18 unter clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)Linux implementiert ist .
  • clock_gettime(CLOCK_MONOTONIC, ...)bietet Nanosekundenauflösung, ist monoton. Ich glaube, die 'Sekunden' und 'Nanosekunden' werden separat in 32-Bit-Zählern gespeichert. Somit würde jeder Wrap-Around nach vielen Dutzend Jahren Betriebszeit auftreten. Dies sieht nach einer sehr guten Uhr aus, ist aber unter OS X leider noch nicht verfügbar. POSIX 7 wird CLOCK_MONOTONICals optionale Erweiterung beschrieben .
  • getrusage()stellte sich als die beste Wahl für meine Situation heraus. Es meldet die Benutzer- und Systemzeiten getrennt und wird nicht umbrochen. Die Genauigkeit auf meinem System beträgt 1 µs, aber ich habe es auch auf einem Linux-System (Red Hat 4.1.2-48 mit GCC 4.1.2) getestet und dort betrug die Genauigkeit nur 1 ms.
  • gettimeofday()Gibt die Wanduhrzeit mit (nominal) µs Genauigkeit zurück. Auf meinem System scheint diese Uhr eine Genauigkeit von µs zu haben, dies ist jedoch nicht garantiert, da "die Auflösung der Systemuhr hardwareabhängig ist" . POSIX.1-2008 sagt das . "Anwendungen sollten die clock_gettime()Funktion anstelle der veralteten gettimeofday()Funktion verwenden", daher sollten Sie sich davon fernhalten. Linux x86 und implementiert es als Systemaufruf .
  • mach_absolute_time()ist eine Option für das Timing mit sehr hoher Auflösung (ns) unter OS X. Auf meinem System ergibt dies tatsächlich eine Auflösung von ns. Im Prinzip dreht sich diese Uhr um, speichert jedoch ns mit einer 64-Bit-Ganzzahl ohne Vorzeichen, sodass das Umlaufen in der Praxis kein Problem darstellen sollte. Portabilität ist fraglich.
  • Ich habe eine Hybridfunktion basierend auf diesem Snippet geschrieben , die clock_gettime verwendet, wenn sie unter Linux kompiliert wird, oder einen Mach-Timer, wenn sie unter OS X kompiliert wird, um ns-Genauigkeit sowohl unter Linux als auch unter OS X zu erhalten.

Alle oben genannten Funktionen sind sowohl unter Linux als auch unter OS X verfügbar, sofern nicht anders angegeben. "Mein System" oben ist ein Apple, auf dem OS X 10.8.3 mit GCC 4.7.2 von MacPorts ausgeführt wird.

Schließlich ist hier eine Liste von Referenzen, die ich zusätzlich zu den obigen Links hilfreich fand:


Update : für OS X wurde ab clock_gettime10.12 (Sierra) implementiert. Außerdem teilen sich sowohl POSIX- als auch BSD-basierte Plattformen (wie OS X) das rusage.ru_utimeStrukturfeld.

Douglas B. Staple
quelle
Mac OS X hat nicht clock_gettime, daher die Verwendung gettimeofday(), ein wenig vielseitiger zu sein alsclock_gettime()
Bobobobo
1
Sie haben nicht erwähnt times()(mit einem s), das seit Ausgabe 1 in POSIX existiert. In Bezug auf GNU / Linux: Laut der Manpage clock (3) wurde darüber hinaus clock()ab glibc 2.17 und früher implementiert, aber zur Verbesserung Präzision, es ist jetzt oben implementiert clock_gettime(CLOCK_PROCESS_CPUTIME_ID,...), was auch in POSIX angegeben ist, aber optional ist.
vinc17
2
@starflyer Die Genauigkeit der Uhr ist teilweise durch die Zeit begrenzt, die zum Abrufen der Uhr benötigt wird. Dies liegt daran, dass, wenn ich die Uhr anrufe und die Rückkehr 1 µs dauert, die Zeit, die die Uhr meldet, aus Sicht des Anrufers um 1 µs "aus" ist. Dies bedeutet, dass eine hochgenaue Uhr auch eine geringe Latenz aufweisen muss. Normalerweise hat man also nicht den Kompromiss, von dem Sie sprechen: Die billigsten Uhren sind auch die genauesten.
Douglas B. Staple
3
Außerdem kümmern sich die meisten Uhren nicht um Sommerzeit / Zeitzonen, selbst wenn sie als Wanduhren betrachtet werden . Beide timeund gettimeofdaykehren zumindest heutzutage Sekunden seit der Epoche zurück (auch bekannt als Unix-Zeitstempel). Dies ist unabhängig von Zeitzonen / Sommerzeit.
Schaltsekunden
2
Für Android-Benutzer kann die Verwendung von CLOCK_MONOTONIC problematisch sein, da die App zusammen mit der Uhr möglicherweise angehalten wird. Zu diesem Zweck hat Android den Timer ANDROID_ALARM_ELAPSED_REALTIME hinzugefügt, auf den über ioctl zugegriffen werden kann. Einige Informationen zu diesen und anderen suspendbezogenen Informationen finden Sie hier
Itay Bianco
17

C11 timespec_get

Anwendungsbeispiel unter: https://stackoverflow.com/a/36095407/895245

Die maximal mögliche zurückgegebene Genauigkeit beträgt Nanosekunden, die tatsächliche Genauigkeit ist jedoch implementierungsdefiniert und kann kleiner sein.

Es gibt die Wandzeit zurück, nicht die CPU-Auslastung.

glibc 2.21 implementiert es unter sysdeps/posix/timespec_get.cund leitet es direkt an:

clock_gettime (CLOCK_REALTIME, ts) < 0)

clock_gettimeund CLOCK_REALTIMEsind POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html und man clock_gettimesagt, dass diese Maßnahme Diskontinuitäten aufweisen kann, wenn Sie einige Systemzeiteinstellungen ändern, während Ihr Programm ausgeführt wird.

C ++ 11 chrono

Da wir schon dabei sind, wollen wir sie auch behandeln: http://en.cppreference.com/w/cpp/chrono

GCC 5.3.0 (C ++ stdlib befindet sich in der GCC-Quelle):

  • high_resolution_clock ist ein Alias ​​für system_clock
  • system_clock leitet an die erste der folgenden Optionen weiter, die verfügbar sind:
    • clock_gettime(CLOCK_REALTIME, ...)
    • gettimeofday
    • time
  • steady_clock leitet an die erste der folgenden Optionen weiter, die verfügbar sind:
    • clock_gettime(CLOCK_MONOTONIC, ...)
    • system_clock

Gefragt bei: Unterschied zwischen std :: system_clock und std :: stetiger_takt?

CLOCK_REALTIMEvs CLOCK_MONOTONIC: Unterschied zwischen CLOCK_REALTIME und CLOCK_MONOTONIC?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
1
Tolle Antwort, die die typischen Implementierungen entmystifiziert. Das müssen die Leute wirklich wissen.
Celess