Wie Schreibe ich eine richtige micro-benchmark in Java?
Wie du schreibst (und ausführen) eine richtige micro-benchmark in Java?
Ich bin auf der Suche für einige code-Beispiele und Bemerkungen illustrieren verschiedene Dinge zu denken.
Beispiel: Sollte der benchmark-Messung von Zeit/iteration oder Iterationen/Zeit, und warum?
Verwandte: Ist die Stoppuhr benchmarking akzeptabel?
Siehe [diese Frage][1] von vor ein paar Minuten für einige Verwandte Informationen. edit: sorry, das ist eigentlich nicht die Antwort. Sollte ich gepostet habe, als einen Kommentar. [1]: stackoverflow.com/questions/503877/...
Es war nach der Planung beziehen sich die poster dieser Frage auf eine Frage wie diese, die ich bemerkt, dass diese Frage nicht vorhanden ist. Also hier ist es, ich hoffe, es werden sich versammeln, einige gute Tipps über die Zeit.
Java 9, könnten einige Funktionen für das micro-benchmarking: openjdk.java.net/jeps/230
Ich denke, dass das Gep-Ziel hinzufügen einige micro-benchmark zu den JDK-code, aber ich denke nicht, dass jmh enthalten im JDK...
Wahrscheinlich duplizieren: Wie finde ich Zeit, die Ausführung einer Methode in Java?
Es war nach der Planung beziehen sich die poster dieser Frage auf eine Frage wie diese, die ich bemerkt, dass diese Frage nicht vorhanden ist. Also hier ist es, ich hoffe, es werden sich versammeln, einige gute Tipps über die Zeit.
Java 9, könnten einige Funktionen für das micro-benchmarking: openjdk.java.net/jeps/230
Ich denke, dass das Gep-Ziel hinzufügen einige micro-benchmark zu den JDK-code, aber ich denke nicht, dass jmh enthalten im JDK...
Wahrscheinlich duplizieren: Wie finde ich Zeit, die Ausführung einer Methode in Java?
InformationsquelleAutor John Nilsson | 2009-02-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Tipps zum schreiben von micro-benchmarks von den Machern von Java-HotSpot:
Regel 0: Lesen einem seriösen Papier auf JVMs und micro-benchmarking. Ein guter ist Brian Goetz, 2005. Erwarten Sie nicht zu viel von micro-benchmarks; Sie Messen nur eine begrenzte Anzahl von JVM-performance-Merkmale.
Regel 1: Immer auch ein warm-up phase läuft Ihr test-kernel, den ganzen Weg durch, genug, um die trigger-alle Initialisierungen und compilations, bevor die timing-phase(s). (Weniger Iterationen ist OK, auf der warmup-phase. Die Faustregel ist, mehrere Zehntausende von inneren schleifendurchläufe.)
Regel 2: laufen Immer mit
-XX:+PrintCompilation
,-verbose:gc
usw., so können Sie sicherstellen, dass der compiler und andere Teile der JVM sind nicht dabei unerwartete Arbeit während der timing-phase.Regel 2.1: Drucken, Nachrichten an den Anfang und das Ende-timing-und-warm-up-Phasen, so dass Sie überprüfen können, dass es keine Ausgabe von Regel 2 während der timing-phase.
Regel 3: sich bewusst Sein, der Unterschied zwischen
-client
und-server
, und OSR und fortlaufenden Sammelwerken. Die-XX:+PrintCompilation
flag-Berichte OSR-Zusammenstellungen mit einem at-Zeichen zu Kennzeichnen die nicht-Initiale Einstiegspunkt, zum Beispiel:Trouble$1::run @ 2 (41 bytes)
. Lieber server, client, und regelmäßige, OSR, wenn Sie nach der besten performance.Regel 4: bewusst Sein, Initialisierung Effekte. Nicht das erste mal drucken, während Sie Ihr timing, phase, da sich das drucken und lädt und initialisiert Klassen. Laden Sie keine neuen Klassen außerhalb der warmup-phase (oder finalen reporting phase), es sei denn, Sie werden die Prüfung der Klasse be-insbesondere (und in diesem Fall laden Sie nur die test-Klassen). Regel 2 ist Ihre erste Linie der Verteidigung gegen solche Effekte.
Regel 5: bewusst Sein, deoptimization und Neukompilierung Effekte. Nehmen Sie keine code-Pfad für die erste Zeit, in der timing-phase, denn der compiler kann die junk-und kompilieren Sie den code, basierend auf einem früheren optimistischen Annahme, dass der Pfad wurde nicht benutzt werden. Regel 2 ist Ihre erste Linie der Verteidigung gegen solche Effekte.
Regel 6: Verwenden Sie geeignete Werkzeuge zum Lesen der compiler ist der Meinung, und erwarten Sie, überrascht zu sein von dem code, den es produziert. Untersuchen Sie den code selbst, bevor er Theorien über das, was etwas schneller oder langsamer.
Regel 7: Reduzieren Sie Rauschen in den Messungen. Führen Sie Ihre benchmark auf eine ruhige Maschine, und führen Sie es mehrmals, verwerfen von Ausreißern. Verwenden
-Xbatch
zu serialisieren Sie den compiler mit der Anwendung, und ziehen Sie in Betracht-XX:CICompilerCount=1
um zu verhindern, dass der compiler ausgeführt wird, parallel mit sich selbst. Versuchen Sie Ihr bestes zu reduzieren GC overhead, setzenXmx
(groß genug) entsprichtXms
und verwendenUseEpsilonGC
, wenn es verfügbar ist.Regel 8: Nutzen Sie die Bibliothek für Ihre benchmark, da ist es wahrscheinlich effizienter und wurde schon ausgetestet, die zu diesem Zweck. Wie JMH, Bremssattel oder Bill-und-Pauls-Exzellente UCSD-Benchmarks für Java.
Auch, nie mit System.currentTimeMillis (), es sei denn, Sie OK mit + oder - 15 ms Genauigkeit, die typisch auf den meisten OS + JVM-Kombinationen. Verwenden Sie System.nanoTime() statt.
Einige Papier aus javaOne: azulsystems.com/events/javaone_2009/session/...
Es sollte angemerkt werden, dass
System.nanoTime()
ist nicht garantiert um genauer zu sein, alsSystem.currentTimeMillis()
. Es ist nur garantiert werden mindestens so genau. Es ist in der Regel wesentlich genauer, jedoch.Der Hauptgrund, warum muss man
System.nanoTime()
stattSystem.currentTimeMillis()
ist, dass die ehemaligen ist garantiert streng monoton Steigend. Die Subtraktion der Werte zurückgegeben, zweicurrentTimeMillis
aufrufen kann tatsächlich negative Ergebnisse, möglicherweise, weil die Systemzeit wurde angepasst, indem einige NTP-daemon.InformationsquelleAutor
Ich weiß, diese Frage wurde markiert als beantwortet, aber ich wollte zu erwähnen, zwei Bibliotheken, die helfen, uns zu schreiben, micro-benchmarks
Bremssattel von Google
Erste Schritte-tutorials
JMH von OpenJDK
Erste Schritte-tutorials
jmh ist wahrscheinlich überlegen Bremssattel heutzutage, Siehe auch: groups.google.com/forum/#!msg/mechanische-Sympathie/m4opvy4xq3U/...
InformationsquelleAutor Aravind R. Yarram
Wichtige Dinge für Java-benchmarks sind:
System.gc()
zwischen Iterationen, ist es eine gute Idee, um Sie zwischen den tests, so dass jeder test, der hoffentlich bekommen die einen "sauberen" Speicher, mit zu arbeiten. (Ja,gc()
ist mehr ein Hinweis als eine Garantie, aber es ist sehr wahrscheinlich, dass es wirklich Müll sammeln, in meiner Erfahrung.)Bin ich nur in den Prozess der das Bloggen über die Gestaltung eines benchmarking-Rahmen .NET. Ich habe eine paar von frühere Beiträge, die möglicherweise in der Lage sein, um Ihnen einige Anregungen geben - nicht alles wird geeignet sein, natürlich, aber einige kann es sein.
gc
immer setzt nicht verwendeten Speicher.Gut, das Absicht ist, dass es eigentlich nicht. Zwar ist es nicht unbedingt garantiert, es ist eigentlich ein ziemlich starker Hinweis. Bearbeiten, klarer zu werden.
Ich bin nicht einverstanden mit dem Aufruf System.gc(). Es ist ein Hinweis darauf, das ist alles. Auch nicht "es wird sich hoffentlich etwas tun". Sie sollten nie nennen. Das ist Programmierung, keine Kunst.
Ja, es ist ein Hinweis - aber es ist eine, die ich beobachtet habe, um in der Regel genommen werden. Also, wenn Sie nicht wie mit
System.gc()
, wie Sie vorschlagen, zu minimieren, die garbage collection in einem test durch Objekte erstellt, die in früheren tests? Ich bin pragmatisch, nicht dogmatisch.Ich weiß nicht, was du meinst mit dem "großen fallback". Können Sie näher, und wieder - Sie haben einen Vorschlag zu geben, bessere Ergebnisse? Ich habe explizit sagen, dass es keine Garantie...
InformationsquelleAutor Jon Skeet
jmh ist eine aktuelle Ergänzung zu OpenJDK und geschrieben wurde von einigen Ingenieuren performance von Oracle. Sicherlich einen Blick Wert.
Sehr interessante Stücke von Informationen begraben in die Probe tests, Kommentare.
Siehe auch:
FYI, JEP 230: Microbenchmark Suite ist ein OpenJDK Vorschlag basierend auf diesem Java Microbenchmark-Gurt (JMH) Projekt. nicht machen den Schnitt für Java 9, aber kann später Hinzugefügt werden.
InformationsquelleAutor assylias
Es hängt davon ab, was Sie versuchen zu testen.
Wenn Sie daran interessiert sind, Latenz, verwenden Sie Zeit/iteration und wenn Sie daran interessiert sind, Durchsatz, verwenden Iterationen/Zeit.
InformationsquelleAutor Peter Lawrey
Stellen Sie sicher, dass Sie irgendwie verwenden die Ergebnisse, die berechnet werden, die im Benchmark-code. Ansonsten kann der code optimiert werden entfernt.
InformationsquelleAutor Peter Štibraný
Wenn Sie versuchen, zu vergleichen zwei algorithmen, mindestens zwei benchmarks für jeden, im Wechsel der Reihenfolge. also:
Habe ich gefunden einige deutliche Unterschiede (5-10% manchmal) in der Laufzeit der gleiche Algorithmus in verschiedenen Durchläufen..
Stellen Sie außerdem sicher, dass n ist sehr groß, so dass die Laufzeit der einzelnen Schleifen ist zumindest 10 Sekunden oder so. Je mehr Iterationen, desto mehr bedeutende Persönlichkeiten, die in Ihrem benchmark-Zeit und zuverlässiger Daten.
InformationsquelleAutor Kip
Gibt es viele mögliche Fallstricke für das schreiben von micro-benchmarks in Java.
Erstens: Sie haben zu berechnen, die alle möglichen Ereignisse, die Zeit nehmen, mehr oder weniger zufällig: Garbage collection, Cache-Effekte (von OS nach Dateien und CPU-Speicher), IO etc.
Zweite: Sie nicht Vertrauen können, die Genauigkeit der gemessenen Zeiten für sehr kurze Intervalle.
Drittens: Die JVM optimiert Ihren code während der Ausführung. So unterschiedlich läuft in der gleichen JVM-Instanz wird immer schneller und schneller.
Meine Empfehlungen: Machen Sie Ihre benchmark laufen ein paar Sekunden, das ist zuverlässiger als eine Laufzeit über Millisekunden. Warm-up für die JVM (ausführen der benchmark mindestens einmal ohne Messung, dass der JVM ausgeführt werden kann-Optimierungen). Und führen Sie Ihre benchmark mehrere Male (vielleicht 5 mal) und nehmen den median-Wert. Führen Sie jede micro-benchmark in eine neue JVM-Instanz (nennen Sie für jeden benchmark neue Java -) ansonsten-Optimierung Auswirkungen der JVM beeinflussen kann später ausführen von tests. Nicht ausführen Dinge, die werden nicht ausgeführt, in der warmup-phase (dies könnte trigger-Klasse-laden und Neukompilierung).
InformationsquelleAutor Mnementh
Es sollte auch darauf hingewiesen werden, dass es vielleicht auch wichtig sein, zu analysieren, die Ergebnisse der micro-benchmark beim Vergleich verschiedener Implementierungen. Daher Signifikanz-test gemacht werden sollte.
Dies ist, weil die Umsetzung
A
könnte schneller sein, bei den meisten läuft der benchmark als UmsetzungB
. AberA
könnte auch ein höherer spread, also die gemessene Leistung vonA
nicht von Bedeutung, wenn im Vergleich mitB
.So ist es auch wichtig, zu schreiben und führen Sie eine micro-benchmark korrekt, aber auch, um es richtig zu analysieren.
InformationsquelleAutor SpaceTrucker
http://opt.sourceforge.net/ Java-Micro-Benchmark - control-Aufgaben erforderlich, um festzustellen, vergleichende performance-Merkmale der computer-system auf verschiedenen Plattformen. Kann verwendet werden, um die guide-Optimierung Entscheidungen und Vergleiche zwischen verschiedenen Java-Implementierungen.
InformationsquelleAutor Yuriy
Hinzufügen, um den anderen gute Ratschläge, ich würde auch darauf achten, die folgenden:
Für einige CPUs (z.B. Intel Core i5-Reihe, mit TurboBoost), der Temperatur (und die Anzahl der Kerne, die derzeit verwendet wird, als auch thier-Nutzung Prozent) wirkt sich auf die Geschwindigkeit. Da die CPU dynamisch getaktet wird, kann dies Auswirkungen auf Ihre Ergebnisse. Zum Beispiel, wenn Sie eine single-threaded-Anwendung, die maximale Taktrate (mit TurboBoost) ist höher als für eine Anwendung mit allen Kernen. Deshalb kann es stören Vergleiche von Einzel-und multi-threaded-performance auf einigen Systemen. Beachten Sie, dass die Temperatur und volatages auch beeinflussen, wie lange Turbo-Frequenz beibehalten wird.
Vielleicht ein grundlegend wichtiger Aspekt, dass Sie die direkte Kontrolle über: stellen Sie sicher, dass die Messung das richtige für Sie! Zum Beispiel, wenn Sie
System.nanoTime()
benchmark einer bestimmten bit-code, legen Sie die Anrufe auf die Abtretung an Orten, die Sinn machen, zu vermeiden, Dinge zu Messen, die Sie nicht interessieren. Zum Beispiel sollten Sie nicht tun:Problem ist, du bist nicht sofort immer am Ende der Zeit, wenn der code fertig ist. Versuchen Sie stattdessen Folgendes:
println
, keine separaten header-Zeile oder etwas, undSystem.nanoTime()
bewertet werden als die erste Schritt in der Konstruktion der string arg. Es gibt nichts, was ein compiler kann mit dem ersten, Sie können nicht mit der zweiten, und weder das eine ist auch Sie ermutigen, um zusätzliche Arbeit zu tun, bevor die Aufnahme einer die Zeit anhalten.InformationsquelleAutor Sina Madani