AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Große Abweichung zwischen Now und GetTickCount

Große Abweichung zwischen Now und GetTickCount

Ein Thema von norwegen60 · begonnen am 2. Mai 2020 · letzter Beitrag vom 3. Mai 2020
Antwort Antwort
Seite 1 von 3  1 23   
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
376 Beiträge
 
Delphi 10.3 Rio
 
#1

Große Abweichung zwischen Now und GetTickCount

  Alt 2. Mai 2020, 22:31
Hallo zusammen,

ich bin gerade über etwas gestolpert, das ich nicht erwartet hätte:

Um von einer eventuellen Änderung der Zeit unabhängig zu sein (z.B. Sommer-/Winterzeit, oder Zeitkorrektur) messe ich die Zeit über GetTickCount. Ich weiß, dass die Auflösung irgendwo um die 16ms liegt, aber das ist eigentlich kein Problem.

Durch Zufall habe ich bemerkt, dass die über GetTickCount kalkulierte Zeit teilweise größere Abweichungen bekommen. Zuerst dachte ich es sei irgendwo ein Fehler, aber es lässt sich recht leicht nachvollziehen und Fehler sehe ich da keinen:
Delphi-Quellcode:
procedure TForm7.btStartClick(Sender: TObject);
begin
  iStart := GetTickCount;
  dtStart := now;

  tiTest.Enabled := not tiTest.Enabled;

  lsDelta.Clear;
end;

procedure TForm7.tiTestTimer(Sender: TObject);
var
  dt1, dt2: TDateTime;

begin
  dt1 := now;
  dt2 := dtStart + (GetTickCount - iStart) / (1000 * 24 * 60 * 60);

  lsDelta.Add((dt1-dt2)*24*60*60);
end;
Um das ganze zu visualisieren im Anhang ein Printscreen. Die Kurve hängt auch davon ab, wann man startet. Ich hatte auch mal eine Kurve die ist Sinusförmig rauf und wieder runter, dann aber ziemlich lang um die 10s Abweichung rum gependelt.
Im Chart noch eine zweite Kurve (orange), wo ich die Ticks mit QueryPerformanceCounter erfasst habe.
Über den Timer habe ich alle 1000ms die Abweichung berechnet und im Chart in [s] eingetragen

Hat jemand eine Erklärung?
Und vor allem, wie kann ich die Zeitmessung von Uhrzeit-Veränderungen unabhängig und genau machen?

Verwendet wird Delphi XE und Win7

Grüße
Gerd
Miniaturansicht angehängter Grafiken
timegettickcount.jpg  

Geändert von norwegen60 ( 2. Mai 2020 um 22:36 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
7.847 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 2. Mai 2020, 22:45
Now ist am Ende ein Aufruf von GetLocalTime, das einen SYSTEMTIME Record füllt. Für dieses gilt in den Remarks:
Zitat:
The system can periodically refresh the time by synchronizing with a time source. Because the system time can be adjusted either forward or backward, do not compare system time readings to determine elapsed time.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
376 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 2. Mai 2020, 23:23
Ich weiß nicht ob ich da was missverstehe, aber genau das ist ja der Grund weshalb ich eigentlich nicht mit Now arbeiten will.

Kurzfristig sollte ein Vergleich aber doch kein Problem sein. Da verstehe ich nicht, dass der Wert innerhalb weniger Minuten um bis zu 20 Sekunden schwankt.
Die Uhr läuft doch in der Zeit nicht um 20s "unrund"

Im Anhang das Chart nach 70 min. Da hat sich QueryPerformanceCounter um 0 stabilisiert, GetTickCount nähert sich immer mehr der 20s Abweichung. Die Uhrzeit wurde in der Zeit nicht verstellt.

Beide Achsen im Chart sind [s]
Miniaturansicht angehängter Grafiken
timegettickcount2.jpg  
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.607 Beiträge
 
Delphi 2007 Enterprise
 
#4

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 2. Mai 2020, 23:24
µC (was CPUs letztlich sind) sind schrecklich ungenaue Uhren. Mehr News um 11 (oder kurz davor oder danach).
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
5.316 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 3. Mai 2020, 05:57
Was genau ist deine Absicht?

Wenn du Zeiten miteinander vergleichen willst und dich dabei auch nicht von Dingen wie Sommer/Winterzeit
-Umstellungen aus dem Takt bringen lassen willst dann nimmt man keine lokale Uhrzeit sondern die Zeit in UTC. Für die Anzeige eines TDateTime für den Benutzer auf dem Bildschirm kann man dann UTC wieder in die lokale Zeitzone umrechnen.
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.291 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 3. Mai 2020, 06:21
Du arbeitest in deinem Beispiel mit, im übertragenen Sinn, Äpfel, Birnen und Pfirsichen

Now ist, wie Uwe schon angemerkt hat, die normal Systemzeit abhängig von der Zeitzone usw. Dabei wird, in Delphi, das ganze als TDateTime-Wert gespeichert. Dieser gibt im Vorkomma Teil die Anzahl der Tage seit dem 30.12.1899 (frag mich bitte nicht warum dieses Datum) an, im Nachkomma Teil, den Anteil der Zeit, die von den 24 Stunden vergangen sind an.

GetTickCount (besser GetTickCount64) gibt dir die Millisekunden seit Systemstart an. Damit ist das ganze soweit unabhängig von irgendwelchen Datums-/Uhrzeiten.

QueryPerformanceCounter ist ähnlich, aber wesentliche genauer. Abhängig ist das ganze aber von der Frequenz, in der gemessen werden kann (QueryPerformanceFrequency).

Was ich an deinem Beispiel kritisch sehen ist folgende Zeile:

Code:
dt2 := dtStart + (GetTickCount - iStart) / (1000 * 24 * 60 * 60);
Denn hier mischt du einen Wert, basieren auf der aktuellen Systemzeit (mit Zeitzone und Sommer-/Winterzeit), mit einem Wert basierend auf dem Systemstart. Noch dazu mit unterschiedlichen Datentypen (Integer und Double).

Je nachdem welche Zeitintervalle zu erwarten sind, würde ich auf TDateTime komplett verzichten und nur entweder mit GetTickCount64 oder QueryPerformanceCounter arbeiten. Wenn die Zeitintervalle größer sind, dann wie Günther schon anmerkte, mit TDateTime auf UTC.

Hoffe das hilft dir weiter.
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
376 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 3. Mai 2020, 08:19
Hallo zusammen,

ich glaube nicht dass ich Äpfel mit Birnen vergleiche. Ich vergleiche nur unterschiedliche Arten die eigentlich immer gleiche Zeit zu erfassen.

In dem Programm das ich betreue, werden zu bestimmten Zeitpunkten Messungen vorgenommen. Da muss in definierten Intervallen auch über längere Zeit (z.B. 30 Tage) innerhalb +/- 10 s gemessen werden (z.B. 30 Tage alle 60 Minuten oder aber auch 20 Minuten alle 2 Minuten)

Zu dem Messzeitpunkt wird auch die Datum/Uhrzeit dokumentiert. Wenn jetzt hin und wieder die Uhr nachgestellt wird, kann man das erklären. Wenn z.B. über den Sommer-/Winterzeit-Wechsel getestet wird, kann es sein, dass Prüfpunkt 11 um 2:45 gemessen wurde, Prüfpunkt 12 dann um 2:15. Um das zu erklären, soll das Programm künftig die Uhrzeit und eine "normierte Uhrzeit" vergleichen. Ist die Abweichung größer als 3s erfolgt ein Eintrag in ein Audittrail, dass die Uhr von außen verstellt wurde. Damit ist nachvollziehbar, warum sich die Benutzer-Uhr und unser Zeitgeber unterscheiden (Und damit auch die u.U. vom Benutzer über die eingetragenen Uhrzeiten nachgerechneten Intervalle).
Wenn aber solch seltsame Dinge auftreten wie in dem Chart kann man das kaum erklären. Bei einem Kurzzeittest, wo der Messintervall vielleicht nur 2 Minuten beträgt, glaubt niemand, dass die Uhrzeit halt mal 20s, mal 5s und dann wieder 20s korrigiert wurde.

Und egal, ob ich die Zeitdifferenz dann in Millisekunden (Integer) oder als Zeit (Double oder TDateTime) umrechne, sollten die in minimalen Grenzen gleich sein.

Im Anhang der Chart nachdem er die Nacht durchgelaufen ist (33600 s = 9:20 Stunden)
Wie man sieht sind die seltsamen Schwankungen zwei mal aufgetreten.
Die Messung der Dauer über QueryPerformanceCounter stimmt streckenweise ziemlich genau mit der überein, die ich über die Uhrzeiten gemessen habe.
GetTickCount weicht mittlerweile über 70s von der Zeit und QueryPerformanceCounter ab.

Ich glaube nicht, dass daran der folgende Code was ändert
Code:
dt2 := dtStart + (GetTickCount - iStart) / (1000 * 24 * 60 * 60);
Damit erschaffe ich mir nur eine isoliert Zeit. Ich werde es aber ausprobieren, ob sich was ändert wenn ich die Zeiten nur bei der Darstellung in eine einheitliches Format (dezimale Sekunden) ändere.

In der Nacht ist mir aber noch eine andere Vermutung gekommen. Das Programm incl. IDE läuft in einer VirtualBox. Vielleicht hat die negative Einflüsse.

Ich melde mich wenn ich dazu mehr weiß
Miniaturansicht angehängter Grafiken
timegettickcount3.jpg  
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
376 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 3. Mai 2020, 09:17
Ein kurzer Zwischenstand. Es sieht so aus, als wenn die Ursache in VirtualBox liegt. Im Anhang die Charts im direkten Vergleich.
  • Linkes Chart: Auf dem PC mit Win10: Nur wenige ms Abweichung und QueryPerfom genauer als GetTickCount
  • Rechtes Chart: In VirtualBox mit Win7: Zeiten schwanken zuerst und fangen dann an zu wandern
GetTickCount64 gibt es in XE noch nicht, sonst hätte ich es ausprobiert
Bleibt für mich noch die Frage, was stimmt denn jetzt auf VirtualBox am genausten?
Ich werde noch manuelle Test mit einer Stoppuhr und ClickButton machen

Der aktuelle Code:
Delphi-Quellcode:
procedure TForm7.btStartClick(Sender: TObject);
begin
  iStartTickCount := GetTickCount;
  iStartPerfCount := GetTickStart;
  dtStartTime := now;

  tiTest.Enabled := not tiTest.Enabled;

  lsDelta.Clear;
end;

procedure TForm7.tiTestTimer(Sender: TObject);
var
  dtDeltaTime: TDateTime;
  iDeltaTickCount: Int64;
  iDeltaPerfCount: Int64;

  rDeltaSecTime, rDeltaSecTickCount, rDeltaSecPerfCount: Double;

begin
  dtDeltaTime := now - dtStartTime;
  iDeltaTickCount := GetTickCount - iStartTickCount;
  iDeltaPerfCount := GetTickDelta(iStartPerfCount);

  rDeltaSecTime := dtDeltaTime * 24 * 60 * 60;
  rDeltaSecTickCount := iDeltaTickCount / 1000;
  rDeltaSecPerfCount := iDeltaPerfCount / 1000;

  lsDelta.Add(rDeltaSecTime - rDeltaSecTickCount);
  lsDeltaQ.Add(rDeltaSecTime - rDeltaSecPerfCount);
end;
Damit die Ergebnisse zwischen altem und neuen Code vergleichbar sind, habe ich als Basis die Uhrzeit gelassen
Miniaturansicht angehängter Grafiken
timegettickcount4.jpg  
  Mit Zitat antworten Zitat
KarstenK

Registriert seit: 4. Dez 2007
Ort: Bärenthal
27 Beiträge
 
Delphi 2009 Enterprise
 
#9

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 3. Mai 2020, 09:30
Hallo,

zu "The system can periodically refresh the time by synchronizing with a time source."

Die Zeitsynchronisierung per NTP ist in Windows etwas magic, es passiert nicht auf einmal, wenn die Zeitdifferenz klein ist, sondern past sich mit der Zeit an. (daher mein Interesse)

Schalte mal alle Netzwerkverbindungen aus um diesen Effekt auszuschliessen.

20 sec halte ich aber für nicht realistisch (scalierung in der Visualisierung?). Bei mir sind es -3 bis +3 ms (Ausreisser bis 9ms).

Kannst Du das Projekt mal hochladen?

Auf welcher hardware laufen deine Tests?
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.291 Beiträge
 
Delphi 10.3 Rio
 
#10

AW: Große Abweichung zwischen Now und GetTickCount

  Alt 3. Mai 2020, 09:38
Ok, das mit der Virtualisierung erklärt ein bischen was.

Wenn ich das mit der Virtualisierung (bin da soz. ein Noob) richtig verstanden hab, müssen die ganzen Aufrufe (QPC bzw. getTickCount) erstmal durch die Virtualisierungssoftware und dann ans Basis-BS geschleift werden. Das kostet natürlich Zeit, je nachdem was im Hintergrund vom Basis-BS noch läuft auch unterschiedlich lange.

Wenn ich mir die Charts aber so anschau, würd ich sagen ist QPC doch einiges genauer. Auch deine Aussage hinsichtlich, das die QPC - Werte sich auf einem Niveu einpendeln deutet darauf hin, das QPC hier die zuverlässigeren Werte liefert.
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2020 by Daniel R. Wolf