it-swarm.com.de

Warum ist System.nanoTime () langsamer (in Leistung) als System.currentTimeMillis ()?

Heute habe ich einen kleinen Benchmark gemacht, um die Geschwindigkeitsleistung von System.nanoTime() und System.currentTimeMillis() zu testen:

long startTime = System.nanoTime();

for(int i = 0; i < 1000000; i++) {
  long test = System.nanoTime();
}

long endTime = System.nanoTime();

System.out.println("Total time: "+(endTime-startTime));

Das sind die Ergebnisse:

System.currentTimeMillis(): average of 12.7836022 / function call
System.nanoTime():          average of 34.6395674 / function call

Warum sind die Unterschiede in der Fahrgeschwindigkeit so groß?

Benchmark-System:

Java 1.7.0_25
Windows 8 64-bit
CPU: AMD FX-6100
59
Frithjof

Von diesem Oracle-Blog :

System.currentTimeMillis() wird mit .__ implementiert. GetSystemTimeAsFileTime-Methode, die im Wesentlichen nur das niedrige .__ liest. Zeitwert für die Auflösung, den Windows beibehält. Das Lesen Die globale Variable ist natürlich sehr schnell - ungefähr 6 Zyklen gemäß berichtete Informationen. 

System.nanoTime() wird mit .__ implementiert. QueryPerformanceCounter/ QueryPerformanceFrequency API (falls verfügbar, wird ____ ansonsten zurückgegeben. currentTimeMillis*10^6). QueryPerformanceCounter(QPC) wird auf verschiedene Arten implementiert Abhängig von der verwendeten Hardware. Normalerweise wird __. entweder der programmierbare Intervall-Timer (PIT) verwendet. , oder der ACPI-Power Management-Timer (PMT) oder der Timestamp-Counter (TSC) auf CPU-Ebene . Für den Zugriff auf PIT/PMT müssen langsame I/O-Port-Anweisungen und als Ergebnis ausgeführt werden Die Ausführungszeit für QPC liegt in der Größenordnung von Mikrosekunden. Im Gegensatz dazu liegt der TSC in der Größenordnung von 100 Taktzyklen (zum Lesen des TSC vom Chip und zum Umwandeln in einen Zeitwert ) auf der Betriebsfrequenz).

Vielleicht beantwortet das die Frage. Die beiden Verfahren verwenden eine unterschiedliche Anzahl von Taktzyklen, wodurch die spätere langsamer wird.

Weitere in diesem Blog in der Schlussfolgerung:

Wenn Sie sich für das Messen/Berechnen der abgelaufenen Zeit interessieren, verwenden Sie immer System.nanoTime (). Bei den meisten Systemen wird eine Auflösung in der Größenordnung von Mikrosekunden angegeben. Beachten Sie jedoch, dass für diesen Aufruf können Mikrosekunden benötigt werden auf einigen Plattformen.

64
Rohit Jain

Die meisten Betriebssysteme (Sie haben nicht erwähnt, welches Sie verwenden) verfügen über einen Zähler/Takt im Speicher, der eine Genauigkeit von Millisekunden bietet (oder nahe daran liegt). Für die Genauigkeit im Nanosekundenbereich müssen die meisten einen Hardwarezähler lesen. Die Kommunikation mit der Hardware ist langsamer als das Lesen eines bereits im Speicher befindlichen Werts.

24
Eelke

Dies kann nur unter Windows der Fall sein. Siehe diese Antwort auf eine ähnliche Frage.

Grundsätzlich liest System.currentTimeMillis() nur eine von Windows gepflegte globale Variable (was von geringer Granularität ist), während System.nanoTime() tatsächlich IO -Operationen ausführen muss.

4

Sie messen das unter Windows, nicht wahr? Ich habe diese Übung 2008 durchlaufen. NanoTime IS] ist unter Windows langsamer als currentTimeMillis. Wie ich mich erinnere, ist Nanotime unter Linux schneller als currentTimeMillis und sicherlich schneller als unter Windows.

Beachten Sie Folgendes: Wenn Sie versuchen, das Aggregat mehrerer Vor-Millisekunden-Operationen zu messen, müssen Sie die Nanotime so verwenden, als wäre die Operation in weniger als einer Tausendstelsekunde beendet. Wenn Sie currentTimeMillis vergleichen, wird die Operation als sofort angezeigt 1.000 davon werden also immer noch sofort sein. Möglicherweise möchten Sie Nanotime verwenden und dann auf die nächste Millisekunde runden. Wenn also eine Operation 8000 Nanosekunden dauert, wird sie als 1 Millisekunde und nicht als 0 gezählt.

1
Walt Corey

Möglicherweise möchten Sie Nanotime verwenden und dann auf die nächste Millisekunde runden. Wenn also eine Operation 8000 Nanosekunden dauert, wird sie als 1 Millisekunde und nicht als 0 gezählt.

Arithmetische Anmerkung:

8000 Nanosekunden sind 8 Mikrosekunden sind 0,008 Millisekunden. Die Rundung dauert 0 Millisekunden.

0
dave