Genauigkeit Vs. Präzision
Was würde Ich mag es , wissen , ob ich verwenden sollte System.currentTimeMillis () oder System.nanoTime () , wenn mein Objekt der Positionen in meinem Spiel zu aktualisieren? Ihre Bewegungsänderung ist direkt proportional zur seit dem letzten Anruf verstrichenen Zeit, und ich möchte so genau wie möglich sein.
Ich habe gelesen, dass es einige schwerwiegende Probleme mit der Zeitauflösung zwischen verschiedenen Betriebssystemen gibt (nämlich, dass Mac / Linux eine Auflösung von fast 1 ms hat, während Windows eine Auflösung von 50 ms hat ??). Ich verwende meine Apps hauptsächlich unter Windows und eine Auflösung von 50 ms scheint ziemlich ungenau zu sein.
Gibt es bessere Optionen als die beiden, die ich aufgelistet habe?
Anregungen / Kommentare?
quelle
nanoTime
ist in der Regel wesentlich genauer als currentTimeMillis, aber es ist auch ein relativ teurer Anruf.currentTimeMillis()
läuft in wenigen (5-6) CPU-Uhren, nanoTime hängt von der zugrunde liegenden Architektur ab und kann über 100 CPU-Uhren sein.System.currentTimeMillis()
: pzemtsov.github.io/2017/07/23/the-slow-currenttimemillis.htmlAntworten:
Wenn Sie nur nach äußerst präzisen Messungen der verstrichenen Zeit suchen , verwenden Sie
System.nanoTime()
.System.currentTimeMillis()
gibt Ihnen die genauestmögliche verstrichene Zeit in Millisekunden seit der Epoche,System.nanoTime()
gibt Ihnen jedoch eine nanosekundengenaue Zeit relativ zu einem beliebigen Punkt.Aus der Java-Dokumentation:
Um beispielsweise zu messen, wie lange die Ausführung von Code dauert:
Siehe auch: JavaDoc System.nanoTime () und JavaDoc System.currentTimeMillis () für weitere Informationen.
quelle
currentTimeMillis
sich dies aufgrund der Sommerzeit ändern? Der DST-Schalter ändert nicht die Anzahl der Sekunden nach der Epoche. Es kann eine "Wanduhr" sein, aber sie basiert auf UTC. Sie müssen anhand Ihrer Zeitzonen- und Sommerzeiteinstellungen bestimmen, was dies für Ihre Ortszeit bedeutet (oder andere Java-Dienstprogramme verwenden, um dies für Sie zu tun).Da hat das sonst niemand erwähnt ...
Es ist nicht sicher, die Ergebnisse von
System.nanoTime()
Aufrufen zwischen verschiedenen Threads zu vergleichen . Selbst wenn die Ereignisse der Threads in einer vorhersagbaren Reihenfolge auftreten, kann der Unterschied in Nanosekunden positiv oder negativ sein.System.currentTimeMillis()
ist sicher für die Verwendung zwischen Threads.quelle
The values returned by this method become meaningful only when the difference between two such values, obtained within the same instance of a Java virtual machine, is computed.
nanoTime()
sagt: Der gleiche Ursprung wird von allen Aufrufen dieser Methode in einer Instanz einer virtuellen Java-Maschine verwendet; Andere Instanzen virtueller Maschinen verwenden wahrscheinlich einen anderen Ursprung. was bedeutet , dass sie nicht das gleiche über Threads zurück.Update von Arkadiy : Ich habe unter
System.currentTimeMillis()
Oracle 7 in Windows Java 8 ein korrekteres Verhalten beobachtet . Die Zeit wurde mit einer Genauigkeit von 1 Millisekunde zurückgegeben. Der Quellcode in OpenJDK hat sich nicht geändert, daher weiß ich nicht, was das bessere Verhalten verursacht.David Holmes von Sun hat vor ein paar Jahren einen Blog-Artikel veröffentlicht, der einen sehr detaillierten Überblick über die Java-Timing-APIs (insbesondere
System.currentTimeMillis()
undSystem.nanoTime()
) gibt, wann Sie welche verwenden möchten und wie sie intern funktionieren.Innerhalb der Hotspot-VM: Uhren, Timer und Planungsereignisse - Teil I - Windows
Ein sehr interessanter Aspekt des von Java unter Windows für APIs mit einem zeitgesteuerten Warteparameter verwendeten Timers ist, dass sich die Auflösung des Timers abhängig davon ändern kann, welche anderen API-Aufrufe möglicherweise getätigt wurden - systemweit (nicht nur im jeweiligen Prozess) . Er zeigt ein Beispiel, in dem die Verwendung
Thread.sleep()
diese Auflösungsänderung verursacht.quelle
GetSystemTimeAsFileTime
in XP vs 7. Siehe arbeitete hier für weitere Einzelheiten (tl; dr es genauer bekam , da das gesamte System einige genauere Timing Methoden eingeführt).System.nanoTime()
wird in älteren JVMs nicht unterstützt. Wenn das ein Problem ist, bleiben Sie beicurrentTimeMillis
In Bezug auf die Genauigkeit sind Sie fast richtig. Hat auf einigen Windows-Computern
currentTimeMillis()
eine Auflösung von ca. 10 ms (nicht 50 ms). Ich bin mir nicht sicher warum, aber einige Windows-Computer sind genauso genau wie Linux-Computer.Ich habe GAGETimer in der Vergangenheit mit mäßigem Erfolg verwendet.
quelle
Wie bereits erwähnt, handelt es sich bei currentTimeMillis um die Uhrzeit, die sich aufgrund der Sommerzeit, der Änderung der Zeiteinstellungen, der Schaltsekunden und der Internetzeitsynchronisierung ändert. Wenn Ihre App von monoton ansteigenden Werten für die verstrichene Zeit abhängt, bevorzugen Sie möglicherweise stattdessen nanoTime.
Sie könnten denken, dass die Spieler während des Spiels nicht an den Zeiteinstellungen herumspielen, und vielleicht haben Sie Recht. Unterschätzen Sie jedoch nicht die Störung aufgrund der Internet-Zeitsynchronisierung oder möglicherweise von Remotedesktopbenutzern. Die nanoTime-API ist gegen diese Art von Störung immun.
Wenn Sie die Uhrzeit verwenden möchten, aber Diskontinuitäten aufgrund der Internet-Zeitsynchronisierung vermeiden möchten, sollten Sie einen NTP-Client wie Meinberg in Betracht ziehen, der die Taktrate so einstellt, dass sie auf Null gesetzt wird, anstatt nur die Uhr regelmäßig zurückzusetzen.
Ich spreche aus persönlicher Erfahrung. In einer von mir entwickelten Wetteranwendung bekam ich zufällig auftretende Windgeschwindigkeitsspitzen. Es dauerte eine Weile, bis mir klar wurde, dass meine Zeitbasis durch das Verhalten der Uhrzeit auf einem typischen PC gestört wurde. Alle meine Probleme verschwanden, als ich anfing, nanoTime zu verwenden. Konsistenz (Monotonie) war für meine Anwendung wichtiger als rohe Präzision oder absolute Genauigkeit.
quelle
System.currentTimeMillis()
meldet die verstrichene Zeit (in Millisekunden) seit der Unix / Posix-Epoche, die Mitternacht, 1. Januar 1970 UTC, ist. Da UTC niemals an die Sommerzeit angepasst wird, wird dieser Wert nicht ausgeglichen, wenn lokale Zeitzonen die lokalen Zeiten für die Sommerzeit hinzufügen oder versetzen. Darüber hinaus glättet die Java-Zeitskala Schaltsekunden, sodass die Tage weiterhin 86.400 Sekunden zu haben scheinen.Ja, wenn eine solche Genauigkeit erforderlich ist, verwenden Sie
System.nanoTime()
diese. Beachten Sie jedoch, dass Sie eine Java 5+ JVM benötigen.Auf meinen XP-Systemen wird die Systemzeit mit dem folgenden Code auf mindestens
100 Mikrosekunden und278 Nanosekunden gemeldet :quelle
Verwenden Sie für Spielgrafiken und reibungslose Positionsaktualisierungen
System.nanoTime()
anstelle vonSystem.currentTimeMillis()
. Ich habe in einem Spiel von currentTimeMillis () zu nanoTime () gewechselt und eine deutliche visuelle Verbesserung der Bewegungsruhe erzielt.Während eine Millisekunde so aussieht, als ob sie bereits präzise sein sollte, ist dies visuell nicht der Fall. Folgende Faktoren
nanoTime()
können sich verbessern:Wie andere Antworten vermuten lassen, verursacht nanoTime bei wiederholtem Aufruf Leistungskosten. Am besten rufen Sie es nur einmal pro Frame auf und verwenden denselben Wert, um den gesamten Frame zu berechnen.
quelle
Ich habe gute Erfahrungen mit Nanotime gemacht . Es liefert eine Wanduhrzeit in zwei Längen (Sekunden seit der Epoche und Nanosekunden innerhalb dieser Sekunde) unter Verwendung einer JNI-Bibliothek. Es ist mit dem vorkompilierten JNI-Teil für Windows und Linux verfügbar.
quelle
System.currentTimeMillis()
ist für die verstrichene Zeit nicht sicher, da diese Methode empfindlich auf Änderungen der System-Echtzeituhr des Systems reagiert. Du solltest benutzenSystem.nanoTime
. Weitere Informationen finden Sie in der Hilfe zum Java-System:Informationen zur nanoTime-Methode:
Wenn Sie
System.currentTimeMillis()
Ihre verstrichene Zeit nutzen, kann dies negativ sein (Zurück <- in die Zukunft)quelle
Eine Sache hier ist die Inkonsistenz der nanoTime-Methode. Sie liefert keine sehr konsistenten Werte für dieselbe Eingabe. currentTimeMillis ist in Bezug auf Leistung und Konsistenz viel besser und hat, obwohl nicht so genau wie nanoTime, eine geringere Fehlerquote und damit mehr Genauigkeit in seinem Wert. Ich würde daher vorschlagen, dass Sie currentTimeMillis verwenden
quelle