Unterschied zwischen steady_clock und system_clock?

7

Ich versuche zu sehen, ob meine Daten 120 Sekunden alt sind oder nicht, indem ich auf den Zeitstempel der Daten schaue, also habe ich den folgenden Code:

%Vor%

Im obigen Code data_holder->getTimestamp() ist uint64_t, der den Zeitstempel in Millisekunden zurückgibt.

Jetzt, wenn ich now Variablenwert ausdrucke, sehe ich 10011360 und wenn ich data_holder->getTimestamp() Wert ausdrucke das ist 1437520382241 , also sollte die Differenz von jetzt und Datenhalter Zeitstempel negativ sein, oder? Warum kommt es so positiv wie in den folgenden Logs gezeigt?

%Vor%

Sieht mein Code oben richtig aus? Und aus dem obigen Zeitstempel des Datenhalters sieht es nicht so aus, als wären es 120 Sekunden alte Daten, also habe ich das Gefühl, dass in meinem Code etwas nicht stimmt? Da, wenn ich den Zeitstempel des Dateninhabers in die tatsächliche Zeit umwandele (unter Verwendung des Epochenkonverters) und dann wie oben gezeigt mit der Protokollzeit vergleiche, ist es fast gleich.

Ich verwende steady_clock wie oben gezeigt. Muss ich system_clock hier benutzen? Was ist der Unterschied zwischen steady_clock vs system_clock in Laien. Ich führe diesen Code auf Ubuntu 14.04 Box.

    
user1950349 22.07.2015, 01:03
quelle

3 Antworten

20

Fragen in umgekehrter Reihenfolge beantworten:

  

Was ist der Unterschied zwischen steady_clock vs system_clock in Laien   Begriffe.

Wenn Sie ein system_clock in Ihrer Hand halten, würden Sie es eine Uhr nennen, und es würde Ihnen sagen, wie spät es ist.

Wenn Sie ein steady_clock in Ihrer Hand halten, würden Sie es eine Stoppuhr nennen, und es würde Ihnen sagen, wie schnell jemand eine Runde gefahren ist, aber es würde Ihnen nicht sagen, wie spät es ist es ist.

Wenn Sie müssten, könnten Sie jemanden mit Ihrer Uhr eine Runde rennen lassen. Aber wenn Ihre Uhr (wie meine) regelmäßig mit einer anderen Maschine (wie der Atomuhr in Boulder CO) redet, um sich selbst auf die aktuelle Zeit zu korrigieren, könnte es kleinere Fehler beim Timing dieser Runde geben. Die Stoppuhr wird diesen Fehler nicht machen, aber sie kann Ihnen auch nicht sagen, was die korrekte aktuelle Zeit ist.

  

Sieht mein Code oben richtig aus?

Nein. Und selbst wenn es Ihnen vernünftige Antworten geben würde, würde ich nicht sagen, dass es richtig ist. Fühle dich nicht schlecht, das ist ein Anfängerfehler, den viele Leute mit der <chrono> -Bibliothek machen.

Es gibt eine einfache Regel, der ich mit der <chrono> -Bibliothek folge. Die Regel ist eigentlich nicht ganz korrekt (also ist es eine Richtlinie). Aber es ist nah genug, um eine Richtlinie zu sein, die fast immer befolgt wird:

  

Verwenden Sie nicht count() .

Und eine logische Folge:

  

Verwenden Sie nicht time_since_epoch() .

Die <chrono> -Bibliothek wurde um ein typsicheres -System herum entwickelt, das Sie vor Fehlern bei der Konvertierung von Einheiten schützen soll. Wenn Sie versehentlich eine unsichere Konvertierung versuchen, wird der Fehler zur Kompilierungszeit abgefangen (im Gegensatz zu einem Laufzeitfehler).

Die Memberfunktionen count() und time_since_epoch() sind "Escape-Luken" aus diesem typsicheren System ... die nur in Notfällen verwendet werden sollen. Solche Notfälle entstehen, wenn (zum Beispiel) das Komitee es versäumt, Ihnen alle Werkzeuge zur Verfügung zu stellen, die Sie benötigen, um die Arbeit zu erledigen (wie I / O) für die <chrono> -Typen oder wie die Notwendigkeit, mit einer anderen Timing-API zu interagieren über Ganzzahlen.

Überprüfen Sie Ihren Code und andere für die Verwendung von count() und time_since_epoch() und überprüfen Sie jede Verwendung dieser Funktionen: Gibt es any wie der Code neu geschrieben werden könnte, um ihre Verwendung zu beseitigen?

Überprüfen Sie die erste Zeile Ihres Codes:

%Vor%

now ist ein time_point (von steady_clock ). Es sind Einheiten milliseconds , aber zu dieser Zeit bin ich nicht davon überzeugt, dass die Einheiten wichtig sind. Wichtig ist, dass now ein time_point ist, das von steady_clock abgerufen wurde:

%Vor%

Ihre zweite Zeile ist komplizierter:

%Vor%

Beginnen wir mit data_holder->getTimestamp() : Wenn Sie getTimestamp() ändern können, sollten Sie sie so ändern, dass ein time_point anstelle eines uint64_t zurückgegeben wird. Um dies zu tun, müssen Sie die richtigen Einheiten kennen (was Sie tun - Millisekunden), und Sie müssen die richtige Epoche kennen. Die Epoche ist der Zeitpunkt, ab dem Ihre Millisekunden gemessen werden.

In diesem Fall ist 1437520382241ms ungefähr 45,6 Jahre alt. Angenommen, dies ist ein neuer Zeitstempel, vor 45,6 Jahren war sehr nahe am 1970-01-01. Wie sich herausstellt, verwendet jede Implementierung von system_clock() 1970-01-01 als seine Epoche (obwohl jede Implementierung unterschiedliche Einheiten aus dieser Epoche zählt).

Entweder ändern Sie getTimestamp() , um eine time_point<system_clock, milliseconds> zurückzugeben, oder umbrechen Sie die Rückgabe von getTimestamp() mit time_point<system_clock, milliseconds> :

%Vor%

Jetzt ist deine zweite Zeile:

%Vor%

Eine weitere gute Richtlinie:

  

Wenn Sie in Ihrem <chrono> -Code Umrechnungsfaktoren sehen, tun Sie es falsch. <chrono> lebt für die Konvertierung für Sie.

%Vor%

Dieser nächste Schritt ist stilistisch, aber jetzt ist Ihr Code einfach genug, um Ihre überschüssigen Klammern loszuwerden, wenn Ihnen das gefällt:

%Vor%

Wenn Sie die getTimestamp() ändern können, um einen typsicheren Wert zurückzugeben, könnte dieser Code auch wie folgt aussehen:

%Vor%

Ach, auf jeden Fall kompiliert das noch nicht! Die Fehlermeldung sollte etwas in der Art sagen, dass es kein gültiges operator-() zwischen now und dh_ts gibt.

  

Dies ist das Typ-Sicherheitssystem, das Sie vor Laufzeitfehlern schützt!

Das Problem ist, dass time_point s von system_clock nicht von time_point s von steady_clock subtrahiert werden kann (weil die beiden unterschiedliche Epochen haben). Du musst also zu:

wechseln %Vor%

Alles zusammenfügen:

%Vor%

Und in C ++ 14 kann die letzte Zeile etwas übersichtlicher gestaltet werden:

%Vor%

Zusammenfassend:

  • Verwenden Sie count() (außer für E / A) nicht.
  • Verwenden Sie time_since_epoch() (außer für E / A) nicht.
  • Verwenden Sie keine Umrechnungsfaktoren (z. B. 1000).
  • Arbeite damit, bis es kompiliert wird.

Wenn Sie in den obigen vier Punkten erfolgreich sind, werden Sie höchstwahrscheinlich keine Laufzeitfehler feststellen (aber Sie erhalten einen fairen Anteil an Kompilierzeitfehlern).

    
Howard Hinnant 22.07.2015, 04:01
quelle
0

Erste Dinge zuerst

Der Grund dafür, dass Sie einen positiven Wert sehen, ist der unsigned integer wrap-around. Versuchen Sie es und sehen Sie:

%Vor%

Wird der Wert von getTimestamp() erwartet? Wenn nicht, ist es etwas schwierig zu sehen, was falsch ist, ohne die Implementierung von getTimestamp() zu sehen. Es sieht so aus, als ob der Zeitstempel nicht mit der gleichen Uhr gemessen wurde.

Stetig gegenüber der Systemzeit

Die stabile Uhr eignet sich am besten zum Messen von Zeitintervallen. Um aus cppreference.com zu zitieren:

  

Klasse std :: chrono :: steady_clock repräsentiert eine monotone Uhr. Die Zeitpunkte dieser Uhr können nicht abnehmen, wenn sich die physische Zeit vorwärts bewegt. Diese Uhr bezieht sich nicht auf die Wanduhrzeit und eignet sich am besten für die Messung von Intervallen.

Im Gegensatz zur system_clock, die nicht monoton ist (d. h. die Zeit kann sich verringern, wenn der Benutzer beispielsweise die Zeit auf dem Hostcomputer ändert.)

    
Anthony 22.07.2015 01:13
quelle
0

Erste Frage, negative Ganzzahl wird implizit umgewandelt, indem Sie eine Ganzzahl vom Typ "uint64_t" wird und eine riesige positive Ganzzahl wird.

Zweite Frage, system_clock ist eine systemweite Echtzeituhr, und wenn Sie die Systemzeit geändert haben, hat sich die Rückkehrzeit von system_clock geändert. Die steady_clock ist eine physikalische Zeit, so dass Sie sie nicht ändern können.

    
JerryYoung 22.07.2015 11:13
quelle

Tags und Links