Ist System.nanoTime () völlig nutzlos?

153

Wie im Blog-Beitrag Vorsicht vor System.nanoTime () in Java dokumentiert , gibt Javas System.nanoTime () auf x86-Systemen den Zeitwert mithilfe eines CPU- spezifischen Zählers zurück. Betrachten Sie nun den folgenden Fall, mit dem ich die Zeit eines Anrufs messe:

long time1= System.nanoTime();
foo();
long time2 = System.nanoTime();
long timeSpent = time2-time1;

In einem Mehrkernsystem kann es sein, dass der Thread nach dem Messen der Zeit1 für einen anderen Prozessor geplant wird, dessen Zähler kleiner als der der vorherigen CPU ist. Somit könnten wir in time2 einen Wert erhalten, der kleiner als time1 ist. Somit würden wir in timeSpent einen negativen Wert erhalten.

Ist System.nanotime in diesem Fall nicht vorerst so gut wie nutzlos?

Ich weiß, dass das Ändern der Systemzeit keinen Einfluss auf die Nanotime hat. Das ist nicht das Problem, das ich oben beschreibe. Das Problem ist, dass jede CPU einen anderen Zähler behält, seit sie eingeschaltet wurde. Dieser Zähler kann bei der zweiten CPU niedriger sein als bei der ersten CPU. Da der Thread vom Betriebssystem nach dem Abrufen von time1 auf die zweite CPU eingeplant werden kann, ist der Wert von timeSpent möglicherweise falsch und sogar negativ.

pdeva
quelle
2
Ich habe keine Antwort, aber ich stimme Ihnen zu. Vielleicht sollte es als Fehler in der JVM angesehen werden.
Aaron Digulla
2
Dieser Beitrag ist falsch und die Nichtverwendung von TSC ist langsam, aber Sie müssen damit leben: bugs.sun.com/bugdatabase/view_bug.do?bug_id=6440250 Auch TSC kann über Hypervisor nützlich gemacht werden, aber dann ist es wieder langsam.
Bests
1
Und natürlich können Sie in einer virtuellen Maschine laufen, in der eine CPU mitten in einer Sitzung angezeigt werden kann: D
Limited Atonement

Antworten:

206

Diese Antwort wurde 2011 unter dem Gesichtspunkt geschrieben, was das Sun JDK der damaligen Zeit auf Betriebssystemen tatsächlich tat. Das ist eine lange Zeit her! Die Antwort von leventov bietet eine aktuellere Perspektive.

Dieser Beitrag ist falsch und nanoTimesicher. Es gibt einen Kommentar zu dem Beitrag, der auf einen Blog-Beitrag von David Holmes verweist, einem Echtzeit- und Parallelitäts-Typ bei Sun. Es sagt:

System.nanoTime () wird mithilfe der QueryPerformanceCounter / QueryPerformanceFrequency-API implementiert. [...] Der von QPC verwendete Standardmechanismus wird von der Hardware Abstraction Layer (HAL) bestimmt. [...] Diese Standardeinstellung ändert sich nicht nur zwischen Hardware, sondern auch zwischen Betriebssystemen Versionen. Beispielsweise hat Windows XP Service Pack 2 die Verwendung des Energieverwaltungs-Timers (PMTimer) anstelle des Prozessor-Zeitstempelzählers (TSC) geändert, da Probleme mit der nicht synchronisierten TSC auf verschiedenen Prozessoren in SMP-Systemen und aufgrund der Häufigkeit aufgetreten sind kann je nach Energieverwaltungseinstellungen variieren (und damit auch in Bezug auf die verstrichene Zeit).

Also, auf Windows, dies war ein Problem , bis WinXP SP2, aber es ist jetzt nicht.

Ich kann keinen Teil II (oder mehr) finden, der über andere Plattformen spricht, aber dieser Artikel enthält eine Bemerkung, dass Linux auf dieselbe Weise auf dasselbe Problem gestoßen ist und es gelöst hat, mit einem Link zu den FAQ für clock_gettime (CLOCK_REALTIME). , was sagt:

  1. Ist clock_gettime (CLOCK_REALTIME) auf allen Prozessoren / Kernen konsistent? (Ist der Bogen wichtig? ZB ppc, arm, x86, amd64, sparc).

Es sollte oder es wird als fehlerhaft angesehen.

Unter x86 / x86_64 ist es jedoch möglich, dass nicht synchronisierte oder variable Frequenz-TSCs Zeitinkonsistenzen verursachen. 2.4-Kernel hatten wirklich keinen Schutz dagegen, und frühe 2.6-Kernel waren auch hier nicht besonders gut. Ab 2.6.18 ist die Logik zur Erkennung besser und wir greifen normalerweise auf eine sichere Taktquelle zurück.

ppc hat immer eine synchronisierte Zeitbasis, daher sollte dies kein Problem sein.

Wenn Holmes 'Link als Hinweis auf diese nanoTimeAufrufe gelesen werden kann clock_gettime(CLOCK_REALTIME), ist er ab Kernel 2.6.18 auf x86 und immer auf PowerPC sicher (da IBM und Motorola im Gegensatz zu Intel tatsächlich wissen, wie man Mikroprozessoren entwirft).

SPARC oder Solaris werden leider nicht erwähnt. Und natürlich haben wir keine Ahnung, was IBM JVMs tun. Aber Sun JVMs unter modernen Windows- und Linux-Versionen machen das richtig.

BEARBEITEN: Diese Antwort basiert auf den zitierten Quellen. Aber ich mache mir immer noch Sorgen, dass es tatsächlich völlig falsch sein könnte. Einige aktuellere Informationen wären wirklich wertvoll. Ich bin gerade auf einen Link zu einem vier Jahre neueren Artikel über Linux-Uhren gestoßen, der nützlich sein könnte.

Tom Anderson
quelle
13
Sogar WinXP SP2 scheint zu leiden. Ausführen des ursprünglichen Codebeispiels mit void foo() { Thread.sleep(40); }einer negativen Zeit (-380 ms!) Mit einem einzelnen Athlon 64 X2 4200+Prozessor
Luke Usherwood
Ich nehme nicht an, dass dies aktualisiert wurde, wrt. Verhalten unter Linux, BSD oder anderen Plattformen?
Tomer Gabel
6
Gute Antwort, sollte einen Link zur neueren Erforschung dieses Themas hinzufügen
Nitsan Wakart
1
@ SOFe: Oh, das ist eine Schande. Es befindet sich zum Glück im Webarchiv . Ich werde sehen, ob ich eine aktuelle Version finden kann.
Tom Anderson
1
Hinweis: OpenJDK hat die Spezifikation bis OpenJDK 8u192 nicht eingehalten, siehe bugs.openjdk.java.net/browse/JDK-8184271 . Stellen Sie sicher, dass Sie mindestens eine neue Version von OpenJDK 8 oder OpenJDK 11+ verwenden.
Leventov
35

Ich habe ein bisschen gesucht und festgestellt, dass wenn man pedantisch ist, es ja als nutzlos angesehen werden kann ... in bestimmten Situationen ... es hängt davon ab, wie zeitkritisch Ihre Anforderungen sind ...

Schauen Sie sich dieses Zitat auf der Java Sun-Website an:

Die Echtzeituhr und System.nanoTime () basieren beide auf demselben Systemaufruf und damit auf derselben Uhr.

Mit Java RTS basieren alle zeitbasierten APIs (z. B. Timer, periodische Threads, Terminüberwachung usw.) auf dem hochauflösenden Timer. Zusammen mit Echtzeitprioritäten können sie sicherstellen, dass der entsprechende Code zum richtigen Zeitpunkt für Echtzeitbeschränkungen ausgeführt wird. Im Gegensatz dazu bieten gewöhnliche Java SE-APIs nur wenige Methoden, die hochauflösende Zeiten verarbeiten können, ohne dass die Ausführung zu einem bestimmten Zeitpunkt garantiert ist. Die Verwendung von System.nanoTime () zwischen verschiedenen Punkten im Code zur Durchführung von Messungen der verstrichenen Zeit sollte immer genau sein.

Java hat auch eine Einschränkung für die nanoTime () -Methode:

Diese Methode kann nur zur Messung der verstrichenen Zeit verwendet werden und steht in keinem Zusammenhang mit einem anderen Begriff der System- oder Wanduhrzeit. Der zurückgegebene Wert repräsentiert Nanosekunden seit einer festen, aber willkürlichen Zeit (möglicherweise in der Zukunft, daher können die Werte negativ sein). Diese Methode bietet eine Nanosekundengenauigkeit, jedoch nicht unbedingt eine Nanosekundengenauigkeit. Es wird keine Garantie dafür übernommen, wie häufig sich Werte ändern. Unterschiede bei aufeinanderfolgenden Aufrufen, die länger als ungefähr 292,3 Jahre (2 63 Nanosekunden) dauern, berechnen die verstrichene Zeit aufgrund des numerischen Überlaufs nicht genau.

Es scheint, dass die einzige Schlussfolgerung, die gezogen werden kann, darin besteht, dass nanoTime () nicht als genauer Wert herangezogen werden kann. Wenn Sie also keine Zeiten messen müssen, die nur Nanosekunden voneinander entfernt sind, ist diese Methode auch dann gut genug, wenn der resultierende Rückgabewert negativ ist. Wenn Sie jedoch eine höhere Präzision benötigen, empfehlen sie anscheinend die Verwendung von JAVA RTS.

Um Ihre Frage zu beantworten ... no nanoTime () ist nicht nutzlos ... es ist einfach nicht die umsichtigste Methode, die in jeder Situation angewendet werden kann.

Mezoid
quelle
3
> Diese Methode ist auch dann gut genug, wenn der resultierende Rückgabewert negativ ist. Ich verstehe das nicht, wenn der Wert in timepent negativ ist, wie ist es dann überhaupt nützlich, die in foo () benötigte Zeit zu messen?
Pdeva
3
Es ist in Ordnung, denn alles, worüber Sie sich Sorgen machen, ist der absolute Wert der Differenz. dh wenn Ihre Messung die Zeit t ist, in der t = t2 - t1 ist, dann möchten Sie wissen, | t | .... was ist, wenn der Wert negativ ist ... selbst bei dem Mehrkernproblem wird die Auswirkung selten einige sein Nanosekunden sowieso.
Mezoid
3
So sichern Sie @Aaron: Sowohl t2 als auch t1 sind möglicherweise negativ, aber (t2-t1) darf nicht negativ sein.
JFS
2
Aaron: Genau darum geht es mir. t2-t1 sollte niemals negativ sein, sonst haben wir einen Fehler.
Pdeva
12
@pdeva - aber Sie verstehen falsch, was der Arzt sagt. Sie sprechen ein Nicht-Problem an. Es gibt einen Zeitpunkt, der als "0" betrachtet wird. Die von nanoTime () zurückgegebenen Werte sind relativ zu dieser Zeit genau. Es ist eine monoton zunehmende Zeitachse. Möglicherweise erhalten Sie eine Reihe von Zahlen aus dem negativen Teil dieser Zeitleiste. -100, -99, -98(Natürlich viel größere Werte in der Praxis). Sie gehen in die richtige Richtung (zunehmend), daher gibt es hier kein Problem.
ToolmakerSteve
18

Keine Notwendigkeit zu debattieren, verwenden Sie einfach die Quelle. Hier, SE 6 für Linux, machen Sie Ihre eigenen Schlussfolgerungen:

jlong os::javaTimeMillis() {
  timeval time;
  int status = gettimeofday(&time, NULL);
  assert(status != -1, "linux error");
  return jlong(time.tv_sec) * 1000  +  jlong(time.tv_usec / 1000);
}


jlong os::javaTimeNanos() {
  if (Linux::supports_monotonic_clock()) {
    struct timespec tp;
    int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp);
    assert(status == 0, "gettime error");
    jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec);
    return result;
  } else {
    timeval time;
    int status = gettimeofday(&time, NULL);
    assert(status != -1, "linux error");
    jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec);
    return 1000 * usecs;
  }
}
blais
quelle
7
Dies ist nur hilfreich, wenn Sie wissen, was die verwendete API bewirkt. Die verwendete API wird vom Betriebssystem implementiert. Dieser Code ist korrekt. die Spezifikation der verwendeten API (clock_gettime / gettimeofday), aber wie andere betonten, haben einige nicht aktuelle Betriebssysteme fehlerhafte Implementierungen.
Blaisorblade
18

Seit Java 7 System.nanoTime()ist die Sicherheit durch die JDK-Spezifikation garantiert. System.nanoTime()Javadoc macht deutlich, dass alle beobachteten Aufrufe innerhalb einer JVM (dh über alle Threads hinweg) monoton sind:

Der zurückgegebene Wert repräsentiert Nanosekunden seit einer festen, aber willkürlichen Ursprungszeit (möglicherweise in der Zukunft, daher können die Werte negativ sein). 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.

Die JVM / JDK-Implementierung ist dafür verantwortlich, die Inkonsistenzen auszubügeln, die beim Aufrufen der zugrunde liegenden Betriebssystem-Dienstprogramme auftreten können (z. B. die in der Antwort von Tom Anderson genannten ).

Die meisten anderen alten Antworten auf diese Frage (geschrieben 2009–2012) drücken FUD aus, das wahrscheinlich für Java 5 oder Java 6 relevant war, aber für moderne Versionen von Java nicht mehr relevant ist.

Es ist jedoch erwähnenswert, dass es trotz der nanoTime()Sicherheit von JDK-Garantien mehrere Fehler in OpenJDK gab, die dazu führten, dass diese Garantie auf bestimmten Plattformen oder unter bestimmten Umständen nicht eingehalten wurde (z. B. JDK-8040140 , JDK-8184271 ). Derzeit gibt es keine offenen (bekannten) Fehler in OpenJDK nanoTime(), aber die Entdeckung eines neuen solchen Fehlers oder eine Regression in einer neueren Version von OpenJDK sollte niemanden schockieren.

In diesem Sinne sollte Code, der nanoTime()für zeitgesteuertes Blockieren, Warten auf Intervalle, Zeitüberschreitungen usw. verwendet wird, negative Zeitdifferenzen (Zeitüberschreitungen) vorzugsweise als Nullen behandeln, anstatt Ausnahmen auszulösen. Diese Praxis ist auch bevorzugt , weil es mit dem Verhalten aller zeitlichen Warten Methoden in allen Klassen in Einklang steht java.util.concurrent.*, zum Beispiel Semaphore.tryAcquire(), Lock.tryLock(), BlockingQueue.poll()etc.

Dennoch nanoTime()sollte für die Implementierung von zeitgesteuertem Blockieren, Warten auf Intervalle, Zeitüberschreitungen usw. immer noch bevorzugt werden, currentTimeMillis()da letzteres dem Phänomen "Rücklaufzeit" unterliegt (z. B. aufgrund der Serverzeitkorrektur), dh currentTimeMillis()nicht zum Messen von Zeitintervallen geeignet ist überhaupt. Weitere Informationen finden Sie in dieser Antwort .

Anstatt die nanoTime()Messungen der Codeausführungszeit direkt zu verwenden, sollten vorzugsweise spezielle Benchmarking-Frameworks und -Profiler verwendet werden, z. B. JMH und Async-Profiler im Wall-Clock-Profiling-Modus .

leventov
quelle
10

Haftungsausschluss: Ich bin der Entwickler dieser Bibliothek

Das könnte dir besser gefallen:

http://juliusdavies.ca/nanotime/

Es kopiert jedoch eine DLL- oder Unix .so-Datei (Shared Object) in das Home-Verzeichnis des aktuellen Benutzers, damit es JNI aufrufen kann.

Einige Hintergrundinformationen finden Sie auf meiner Website unter:

http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html

Julius Musseau
quelle
@ Julius Hast du die Bibliothek von deiner Seite entfernt?
Nitin Dandriyal
6

Linux korrigiert Diskrepanzen zwischen CPUs, Windows jedoch nicht. Ich schlage vor, Sie gehen davon aus, dass System.nanoTime () nur auf etwa 1 Mikrosekunde genau ist. Eine einfache Möglichkeit, ein längeres Timing zu erzielen, besteht darin, foo () 1000 oder mehr Mal aufzurufen und die Zeit durch 1000 zu teilen.

Peter Lawrey
quelle
2
Könnten Sie eine Referenz angeben (Verhalten unter Linux und Windows)?
JFS
Leider ist das vorgeschlagene Verfahren im Allgemeinen sehr ungenau, da jedes Ereignis, das in den +/- 100 ms Wanduhr-Aktualisierungsschlitz fällt, für Operationen im Subsekundenbereich häufig Null zurückgibt. Die Summe von 9 Operationen mit einer Dauer von jeweils Null ist Null, geteilt durch Neun ist ... Null. Umgekehrt liefert die Verwendung von System.nanoTime () eine relativ genaue Ereignisdauer (ungleich Null), die dann summiert und durch die Anzahl der Ereignisse dividiert wird und einen hochpräzisen Durchschnitt ergibt.
Darrell Teague
@DarrellTeague Das Summieren und Addieren von 1000 Ereignissen entspricht der End-to-End-Zeit.
Peter Lawrey
@DarrellTeague System.nanoTime () ist auf den meisten Systemen auf 1 Mikrosekunde oder besser (nicht 100.000 Mikrosekunden) genau. Die Mittelung vieler Vorgänge ist nur relevant, wenn Sie nur wenige Mikrosekunden benötigen, und nur auf bestimmten Systemen.
Peter Lawrey
1
Entschuldigung, da es einige Verwirrung über die Sprache gab, die beim "Summieren" von Ereignissen verwendet wurde. Ja, wenn die Zeit zu Beginn von beispielsweise 1000 Subsekundenoperationen markiert ist, werden sie ausgeführt, und am Ende wird die Zeit erneut markiert und geteilt - dies würde für ein in der Entwicklung befindliches System funktionieren, um eine gute Annäherung an die Dauer für eine bestimmte Zeit zu erhalten Veranstaltung.
Darrell Teague
5

Absolut nicht nutzlos. Timing-Liebhaber weisen korrekt auf das Multi-Core-Problem hin, aber in Real-Word-Anwendungen ist es oft radikal besser als currentTimeMillis ().

Bei der Berechnung von Grafikpositionen in Bildaktualisierungen führt nanoTime () zu VIEL sanfteren Bewegungen in meinem Programm.

Und ich teste nur auf Mehrkernmaschinen.

Yuvi Masory
quelle
5

Bei der Verwendung von System.nanoTime () wurde eine negative verstrichene Zeit gemeldet. Um klar zu sein, lautet der fragliche Code:

    long startNanos = System.nanoTime();

    Object returnValue = joinPoint.proceed();

    long elapsedNanos = System.nanoTime() - startNanos;

und die Variable 'elapsedNanos' hatte einen negativen Wert. (Ich bin mir sicher, dass der Zwischenaufruf auch weniger als 293 Jahre gedauert hat, was der Überlaufpunkt für Nanos ist, die in Longs gespeichert sind :)

Dies geschah mit einer IBM v1.5 JRE 64-Bit auf IBM P690-Hardware (Multi-Core) unter AIX. Ich habe diesen Fehler nur einmal gesehen, daher scheint er äußerst selten zu sein. Ich kenne die Ursache nicht - ist es ein hardwarespezifisches Problem, ein JVM-Defekt - ich weiß es nicht. Ich kenne auch die Auswirkungen auf die Genauigkeit von nanoTime () im Allgemeinen nicht.

Um die ursprüngliche Frage zu beantworten, halte ich nanoTime nicht für nutzlos - es bietet ein Timing unter einer Millisekunde, aber es besteht ein tatsächliches (nicht nur theoretisches) Risiko, dass es ungenau ist, das Sie berücksichtigen müssen.

Basil Vandegriend
quelle
Leider scheint es sich um ein Betriebssystem- / Hardwareproblem zu handeln. Die Dokumentation besagt, dass die Kernwerte negativ sein können, aber (größeres Negativ minus kleineres Negativ) immer noch ein positiver Wert sein sollte. In der Tat wird davon ausgegangen, dass der Aufruf von nanoTime () im selben Thread immer einen positiven oder negativen Wert zurückgeben sollte. Ich habe dies über viele Jahre auf verschiedenen Unix- und Windows-Systemen noch nie gesehen, aber es klingt möglich, insbesondere wenn die Hardware / das Betriebssystem diesen scheinbar atomaren Vorgang auf mehrere Prozessoren aufteilt.
Darrell Teague
@BasilVandegriend es ist nirgendwo ein Fehler. Gemäß der Dokumentation kann die zweite System.nanoTime () in Ihrem Beispiel selten auf einer anderen CPU ausgeführt werden, und die auf dieser CPU berechneten nanoTime-Werte können zufällig niedriger sein als die auf der ersten CPU berechneten Werte. Also, ein -ve Wert für verstrichene Nanos ist möglich
endlos
2

Dies scheint auf einem Core 2 Duo unter Windows XP und JRE 1.5.0_06 kein Problem zu sein.

In einem Test mit drei Threads sehe ich nicht, dass System.nanoTime () rückwärts geht. Die Prozessoren sind beide beschäftigt, und Threads gehen gelegentlich in den Ruhezustand, um sich bewegende Threads zu provozieren.

[EDIT] Ich würde vermuten, dass dies nur auf physisch getrennten Prozessoren geschieht, dh dass die Zähler für mehrere Kerne auf demselben Chip synchronisiert sind.

Sternenblau
quelle
2
Es wird wahrscheinlich nicht die ganze Zeit passieren, aber aufgrund der Art und Weise, wie nanotime () implementiert wird, ist die Möglichkeit immer da.
Pdeva
Ich würde vermuten, dass dies nur auf physisch getrennten Prozessoren geschieht, dh dass die Zähler für mehrere Kerne auf demselben Chip synchronisiert sind.
Starblue
Auch das hängt von der spezifischen Implementierung des IIRC ab. Aber darum soll sich das Betriebssystem kümmern.
Blaisorblade
1
Die RDTSC-Zähler auf mehreren Kernen desselben x86-Prozessors sind nicht unbedingt synchronisiert - einige moderne Systeme lassen unterschiedliche Kerne mit unterschiedlichen Geschwindigkeiten laufen.
Jules
2

Nein, es ist nicht ... Es hängt nur von Ihrer CPU ab. Überprüfen Sie den High Precision Event Timer, wie / warum die Dinge je nach CPU unterschiedlich behandelt werden.

Lesen Sie im Grunde die Quelle Ihres Java und überprüfen Sie, was Ihre Version mit der Funktion macht. Wenn sie gegen die CPU funktioniert, werden Sie sie ausführen.

IBM schlägt sogar vor, dass Sie es für das Leistungsbenchmarking verwenden (ein Beitrag von 2008, aber aktualisiert).

Ric Tokyo
quelle
Wie alle Implementierungen bahaviour definiert, "Vorbehalt Emptor!"
David Schmitt
2

Ich verweise auf die im Wesentlichen gleiche Diskussion, in der Peter Lawrey eine gute Antwort gibt. Warum erhalte ich mit System.nanoTime () eine negative verstrichene Zeit?

Viele Leute erwähnten, dass in Java System.nanoTime () eine negative Zeit zurückgegeben werden könnte. Ich entschuldige mich dafür, dass ich wiederholt habe, was andere Leute bereits gesagt haben.

  1. nanoTime () ist keine Uhr, sondern ein CPU-Zykluszähler.
  2. Der Rückgabewert wird durch die Häufigkeit geteilt, um wie die Zeit auszusehen.
  3. Die CPU-Frequenz kann schwanken.
  4. Wenn Ihr Thread auf einer anderen CPU geplant ist, besteht die Möglichkeit, dass nanoTime () abgerufen wird, was zu einem negativen Unterschied führt. Das ist logisch. CPU-überzählige Zähler sind nicht synchronisiert.
  5. In vielen Fällen können irreführende Ergebnisse erzielt werden, die Sie jedoch nicht feststellen können, da Delta nicht negativ ist. Denk darüber nach.
  6. (unbestätigt) Ich denke, Sie können sogar auf derselben CPU ein negatives Ergebnis erzielen, wenn die Anweisungen neu angeordnet werden. Um dies zu verhindern, müssten Sie eine Speicherbarriere aufrufen, die Ihre Anweisungen serialisiert.

Es wäre cool, wenn System.nanoTime () die CoreID zurückgeben würde, in der sie ausgeführt wurde.

Wirbel
quelle
1
Alle Punkte außer 3. und 5. sind falsch. 1. nanoTime () ist kein CPU-Zykluszähler, sondern Nano-Zeit . 2. Wie der nanoTime-Wert erzeugt wird, ist plattformspezifisch. 4. Nein, der Unterschied darf laut nanoTime () nicht negativ sein. Angenommen, OpenJDK hat keine Fehler in nanoTime () und es sind derzeit keine ungelösten Fehler bekannt. 6. nanoTime-Aufrufe können innerhalb eines Threads nicht neu angeordnet werden, da es sich um eine native Methode handelt und JVM die Programmreihenfolge respektiert. JVM ordnet native Methodenaufrufe niemals neu an, da es nicht weiß, was in ihnen geschieht, und daher nicht beweisen kann, dass solche Neuordnungen sicher sind.
Leventov
In Bezug auf 5. nanoTime () können Differenzergebnisse zwar irreführend sein, jedoch nicht aus den Gründen, die in anderen Punkten dieser Antwort aufgeführt sind. Aber eher aus Gründen, die hier vorgestellt werden: shipilev.net/blog/2014/nanotrusting-nanotime
leventov
Ironischerweise gab es in Bezug auf 6. einen Fehler in OpenJDK, der speziell auf Neuordnungen zurückzuführen war: bugs.openjdk.java.net/browse/JDK-8184271 . In OpenJDK ist nanoTime () ein intrinsisches Element und es durfte neu angeordnet werden, das war ein Fehler.
Leventov
@leventov, ist die Verwendung von nanotime () sicher? Das heißt, es kann keine negativen Werte zurückgeben und ist zeitlich genau. Ich sehe keinen Sinn darin, eine API-Funktion verfügbar zu machen, die mit Problemen behaftet ist. Dieser Beitrag ist ein Beweis, der 2009 begonnen und 2019 noch kommentiert wurde. Für geschäftskritische Dinge stelle ich mir vor, dass sich die Leute auf Timing-Karten wie Symmetricom
Vortex vom
1
Ihre Nummer 4 sagt über negative Unterschiede , nicht über Werte: "Es besteht die Möglichkeit, nanoTime () zu erhalten, was zu einem negativen Unterschied führt."
Leventov
1

Java ist plattformübergreifend und nanoTime ist plattformabhängig. Wenn Sie Java verwenden - wenn Sie nanoTime nicht verwenden. Ich habe mit dieser Funktion echte Fehler in verschiedenen JVM-Implementierungen gefunden.

Schurke Kilork
quelle
0

In der Java 5-Dokumentation wird auch empfohlen, diese Methode für denselben Zweck zu verwenden.

Diese Methode kann nur zur Messung der verstrichenen Zeit verwendet werden und steht in keinem Zusammenhang mit einem anderen Begriff der System- oder Wanduhrzeit.

Java 5 API Doc


quelle
0

Ändert sich auch, System.currentTimeMillies()wenn Sie die Uhr Ihres Systems ändern, während System.nanoTime()dies nicht der Fall ist. Letzteres ist daher sicherer, um die Dauer zu messen.

RobAu
quelle
-3

nanoTimeist für das Timing extrem unsicher. Ich habe es mit meinen grundlegenden Primalitätstestalgorithmen ausprobiert und es gab Antworten, die für dieselbe Eingabe buchstäblich eine Sekunde voneinander entfernt waren. Verwenden Sie diese lächerliche Methode nicht. Ich brauche etwas, das genauer und präziser ist als Zeit Millis, aber nicht so schlimm wie nanoTime.

Sarvesh
quelle
Ohne Quelle oder bessere Erklärung ist dieser Kommentar nutzlos
ic3