Warum ist mein System.nanoTime() kaputt?
Mich und andere Entwickler auf meine Zeit, aber vor kurzem von einem Core-2-Duo-Maschine bei der Arbeit, um einen neuen Core 2 Quad 9505; beide mit Windows XP SP3 32-bit-JDK 1.6.0_18.
Nach dem tun so, ein paar von unseren automatisierten unit-tests für einige timing/Statistiken/Metriken aggregation code unverzüglich begann zu scheitern, durch das, was scheint lächerlich kommenden Werte wieder aus dem System.nanoTime().
Test-code, der zeigt dieses Verhalten, zuverlässig, auf meinem Rechner ist:
import static org.junit.Assert.assertThat;
import org.hamcrest.Matchers;
import org.junit.Test;
public class NanoTest {
@Test
public void testNanoTime() throws InterruptedException {
final long sleepMillis = 5000;
long nanosBefore = System.nanoTime();
long millisBefore = System.currentTimeMillis();
Thread.sleep(sleepMillis);
long nanosTaken = System.nanoTime() - nanosBefore;
long millisTaken = System.currentTimeMillis() - millisBefore;
System.out.println("nanosTaken="+nanosTaken);
System.out.println("millisTaken="+millisTaken);
//Check it slept within 10% of requested time
assertThat((double)millisTaken, Matchers.closeTo(sleepMillis, sleepMillis * 0.1));
assertThat((double)nanosTaken, Matchers.closeTo(sleepMillis * 1000000, sleepMillis * 1000000 * 0.1));
}
}
Typische Ausgabe:
millisTaken=5001
nanosTaken=2243785148
Läuft es 100x Erträge nano Ergebnissen zwischen 33% und 60% der tatsächlichen Schlafzeit; in der Regel rund 40%, obwohl.
Verstehe ich die Schwächen in der Genauigkeit der Timer in Windows, und habe gelesen, Verwandte threads wie System.nanoTime() konsistent threads?, aber mein Verständnis ist, dass System.nanoTime() ist gedacht für genau den Zweck nutzen wir es :- Messung verstrichene Zeit; genauer als currentTimeMillis().
Weiß jemand, warum es die Rückgabe einer so krassen Ergebnisse? Ist dies wahrscheinlich ein hardware-Architektur-problem (die einzige große Sache, die sich geändert hat ist die CPU - /Motherboard auf diesem Computer)? Ein problem mit der Windows-HAL mit meiner aktuellen hardware? Eine JDK-problem? Sollte ich aufgeben nanoTime()? Sollte ich log ein Fehler irgendwo, oder irgendwelche Vorschläge, wie könnte ich das weiter untersuchen?
UPDATE 19/07 03:15 UTC: Nach dem Versuch finnw s test folgenden Fall ich habe einige mehr Googeln, kommen über Einträge wie bugid:6440250. Es erinnerte mich auch an einige andere seltsame Verhalten bemerkte ich am späten Freitag, wo die pings waren wieder negativ. Also ich habe /usepmtimer zu meinem boot.ini und nun sind alle tests Verhalten sich wie erwartet., und meine pings sind normal zu.
Ich bin ein bisschen verwirrt, warum war dies noch ein Problem, obwohl, von meiner Lektüre dachte ich, TSC vs PMT-Probleme wurden weitgehend behoben, die in Windows XP SP3. Könnte es sein, weil meine Maschine war ursprünglich SP2, und wurde gepatched auf SP3 eher als ursprünglich installiert als SP3? Ich habe jetzt auch Fragen, ob ich sollte die Installation von patches wie bei MS KB896256. Vielleicht sollte ich mit dem corporate desktop team zusammenstellen?
- Hast du eine komplett neue Maschine oder war Ihre aktuelle Maschine aktualisiert halten die alte Windows-installation?
- Völlig neue Maschine, umgebaut auf ein corporate-standard zu bauen.
- funktioniert bei mir unter Windows 7 64 bit neueste JDK 6.
- mögliche Duplikate von System.nanoTime() völlig nutzlos?
- Wenn jemand kommt, der über diese Frage im Jahr 2019 oder später: dies muss nicht ein Problem sein, auf jedem OS seit OpenJDK 8u25 oder in anderen Versionen veröffentlicht, später bis Februar 2019, modulo unbekannte Fehler, die vielleicht noch irgendwo zu verstecken. Sehen bugs.openjdk.java.net/browse/JDK-8045438
Du musst angemeldet sein, um einen Kommentar abzugeben.
War das problem gelöst (geöffnet, einige Vermutungen über die EIGNUNG von nanoTime() auf multi-core-Systeme!) durch hinzufügen /usepmtimer dem Ende meiner C:\boot.ini string; zwingt Windows zu verwenden, die Power Management-timer eher als der TSC. Es ist eine offene Frage, warum ich brauchte, um dies zu tun gegeben, ich bin auf XP SP3, als ich Verstand, dass dies der Standard, aber vielleicht war es aufgrund der Art und Weise, in der meine Maschine wurde gepatched auf SP3.
Auf meinem system (Windows 7 64-Bit, Core i7 980X):
System.nanoTime() verwendet OS-spezifische Aufrufe, so erwarte ich, dass Sie sehen, ein bug in deinem Windows/Prozessor-Kombination.
Werden Sie wahrscheinlich wollen, um die Antworten Lesen zu diesem anderen stack overflow Frage: System.nanoTime() völlig nutzlos?.
In Zusammenfassung, es scheint, dass nanoTime setzt auf Betriebssystem-Timer beeinflusst werden kann, dass durch die Anwesenheit von mehreren CPU-Kernen. Als solche, nanoTime kann nicht sein, dass nützlich, auf bestimmte Kombinationen von OS und CPU, wobei darauf geachtet werden sollte, wenn Sie es im portable Java-code, den Sie beabsichtigen, zur Ausführung auf mehreren Zielplattformen. Es scheint eine Menge von Beschwerden über das web zu diesem Thema, aber nicht viel Konsens über eine sinnvolle alternative.
Ist es schwierig zu sagen, ob das ein bug ist oder nur normale timer-variation zwischen den Kernen.
Einem experiment könnten Sie versuchen, ist die Verwendung von einheimischen fordert, zu zwingen, den thread zu führen, die auf einem bestimmten Kern.
Auch, um auszuschließen, power-management-Effekte, versuchen Sie es drehen in eine Schleife, als eine alternative zu
sleep()
:Wenn Sie sehr unterschiedliche Ergebnisse erhalten, je nach core-Auswahl (z.B. 5000ms auf dem gleichen Kern, aber 2200ms auf verschiedenen Kernen), dass würde vorschlagen, dass das problem nur Natürliche timer variation zwischen den Kernen.
Wenn Sie sehr unterschiedliche Ergebnisse erhalten, vom schlafen vs. spinning, es ist wahrscheinlicher, aufgrund der power-management-Verlangsamung der Uhren.
Wenn keine der vier Ergebnisse sind nahe zu 5000ms, dann könnte es ein bug sein.