2016-05-24 5 views
5

Ich versuche, die Dauer eines bestimmten Zeitraums mit beiden System.nanoTime() und System.currentTimeMillis() zu messen. Und je länger der Zeitraum wird, desto größer ist der Unterschied, den ich aus zwei Messungen erhalte.nanoTime und currentTimeMillis haben unterschiedliche Raten unter Mac OS

Hier ist ein kleiner Ausschnitt, das Problem demonstriert:

public class TimeTest { 

    public static void main(String[] args) throws Exception { 
     long startNanos = System.nanoTime(); 
     long startMillis = System.currentTimeMillis(); 

     while (true) { 
      long nowNanos = System.nanoTime(); 
      long nowMillis = System.currentTimeMillis(); 

      System.out.println((nowMillis - startMillis) - (nowNanos - startNanos)/1000000); 

      Thread.sleep(100); 
     } 
    } 
} 

Wenn auf Mac OS mit jdk läuft 1.8.0_74 gibt es einen klaren Trend, den Rückgang von 2 ms pro Minute um etwa Werte. I.e. Zuerst sehe ich nur 0 und 1, aber nach 10 Minuten gibt es Werte um -20.

konnte ich nur mit jdk8 auf dem Mac ein solches Verhalten beobachten, ist es unter Linux nicht reproduzieren konnten und auf Fenster mit beiden jdk 7 und 8

So ist die Frage: Wer lügt? Ich weiß, dass nanoTime() zur Messung der Dauer bevorzugt werden sollte. Aber in diesem Fall bin ich mir nicht sicher, ob es wahr ist.

Kann jemand etwas zu diesem Thema ausführen?

+0

Ich sehe eine ähnliche Sache unter Windows 7 x64 mit Java 8. – resueman

Antwort

0

Wenn Sie NTP verwenden, wird wahrscheinlich Ihre currentTimeMillis korrigiert, so dass es am ehesten richtig ist. Die nanoTime() basiert auf den Taktzyklen/Taktfrequenz. Wenn diese Frequenz geringfügig davon abweicht, wird Sie eine konstante Drift sehen. Dies sollte nicht auf der Version von Java basieren, sondern auf dem Betriebssystem und der Hardware.

+3

Auf der gleichen Hardware mit Java 7 läuft nicht diese Drift. Ich denke, ich fand sogar die Erklärung in jdk Quellen. http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/f96d42d605e1/src/os/bsd/vm/os_bsd.cpp os :: javaTimeNanos ist zweimal in den Zeilen 1022 und 1048 definiert. Wenn 1022 wird verwendet, dann erscheint die Drift. –

+0

Fehlerbericht für den HotSpot? :) – Nikem

0

Beide liegen :)

Zeit kann nicht mit absoluter Präzision gemessen werden. Jeder Timer in Ihrem Computer wird immer eine kleine Abweichung haben. Da currentTimeMillis und nanoTime von verschiedenen Timern kommen können, ist es völlig natürlich, dass Sie eine Abweichung zwischen den beiden beobachten. Die Drift kann sogar variieren abhängig von Ihrem Computer Betriebszustand (z. B. Arbeitsbelastung auf dem Gerät kann seine Temperatur ändern und wiederum eine geringfügige Veränderung des Taktgenerators verursachen. Diese Effekte sind klein, aber theyre immer da).

In Fällen, in denen es keine Drift zu geben scheint, werden sowohl currentTimeMillis als auch nanoTime entweder vom selben Hardware-Timer gesteuert, oder es wird ein Korrekturmechanismus im Betriebssystem oder in der VM ausgeführt.

+0

Ich verstehe, dass wir die Zeit nicht mit absoluter Präzision messen können. Aber 2 ms pro Minute machen fast 3 Sekunden pro Tag aus, was zu viel scheint. Außerdem habe ich Beweise, dass es eine Möglichkeit gibt, die Drift zu beseitigen, weil sie in jdk7 nicht vorhanden ist. Ich frage mich, ob diese Änderung in jdk absichtlich war und ob es ein bekanntes Problem ist, weil es auf anderen Maschinen auch 100% reproduzierbar ist. –

+0

Es gibt eine sehr einfache Möglichkeit, Drift zu eliminieren: Verwenden Sie für beide die gleiche Zeitgeberquelle. Der Nachteil ist, dass entweder die Granularität von nanoTime dann grob ist oder currentTimeMillis auf einer Hochfrequenzquelle mit einer allgemein höheren Drift basiert. Mein Punkt ist: absolute Drift ist ein * normales * Phänomen und relative Drift ist eine natürliche Folge von unabhängigen Timern. Es könnte gut sein, dass es Änderungen zwischen JREs gab, um * die Granularität * oder * die * Drift * zu verbessern, die den Unterschied verursachen. Wenn man * relative * Drift in JRE7 nicht sieht, heißt das nicht, dass es eine * bessere * Implementierung ist. – Durandal