Angelika Langer Selbstständig

JMH ist von unschätzbarem Wert für Entwickler, die Performancevergleiche auf dem Micro-Level anstellen wollen.

Klaus Kreft Selbstständig

Die Gefahr beim Microbenchmarking mit JMH ist, dass Performancekennzahlen relativ schnell zu beschaffen sind und dann überbewertet werden.

Wir haben uns im letzten Beitrag unserer Serie mit so genannten Microbenchmarks beschäftigt. Sie dienen dem Performancevergleich verschiedener Implementierungsalternativen. Dabei haben wir darauf hingewiesen, wie fehleranfällig Microbenchmarks sind. In diesem Beitrag wollen wir uns das Werkzeug Java Microbenchmark Harness ansehen, kurz JMH. JMH ist ein Benchmarkrahmen, den man für eigene Microbenchmarks verwenden kann. Wobei hilft JMH? Welches Problem löst es?

Wer schon mal einen Microbenchmark selbst gemacht hat, weiß aus Erfahrung, dass es ziemlich viel Arbeit ist, mit einem Benchmark halbwegs verlässliche Performancekennzahlen zu beschaffen. Den größten Teil der Arbeit steckt man in den Benchmarkrahmen, den man sich baut, um darin die auszumessenden Algorithmen ablaufen zu lassen. Wir haben im letzten Beitrag (Java Magazin 12.16) einige der Probleme geschildert, die sich daraus ergeben, dass die Messergebnisse eines Benchmarks u. a. durch die JVM beeinflusst werden. Exemplarisch haben wir einige dieser Einflussfaktoren angeschaut, wie den Garbage Collector oder JIT-Compiler. Weil sie zu irreführenden Messwerten führen können, versucht man, in seinen Benchmarkrahmen verschiedene Maßnahmen einzubauen, mit denen die verzerrenden Effekte der JVM-Aktivitäten vermieden werden, z. B. Aufwärmphasen, explizite Garbage Collection oder wiederholte Messungen in Schleifen.

JMH ist umfangreich und komplex. Es bietet Lösungen für viele Probleme beim Microbenchmarking an. Wir werden uns im Rahmen dieses Beitrags lediglich einen ausgewählten Aspekt anschauen, nämlich die Messwertverfälschungen durch die Monomorphic Call Transformation des JIT-Compilers und wie JMH diese Messwertverzerrungen vermeidet. Anhand eines Beispiels werden wir sehen, wie JMH prinzipiell funktioniert und das Feature „Messmodi“ genauer betrachten.

An sich sieht ein Microbenchmark mit JMH ähnlich aus wie ein Microbenchmark mit eigenem Benchmarkrahmen. Man implementiert die Algorithmen, deren Performance verglichen werden soll, lässt sie im Benchmarkrahmen wiederholt ablaufen, nimmt Zeitstempel und berechnet je Algorithmus eine Performancekennzahl. Dazu kommen sämtliche vor- und nachbereitenden Arbeiten wie das Allozieren und Initialisieren von Daten, welche die Algorithmen brauchen, und sämtliche erwähnten Maßnahmen zur Vermeidung von Messwertverfälschungen.

Im JMH müssen die auszumessenden Algorithmen als Methoden implementiert sein. Diese Methoden werden mit einer speziellen, von JMH definierten Annotation namens @Benchmark gekennzeichnet. Aus diesem annotierten Code generiert JMH den eigentlichen Benchmarkcode, der später abläuft und die Performancemessungen durchführt. Den generierten Benchmark muss man anschließend nur noch starten. Dafür gibt es verschiedene Möglichkeiten: über die Kommandozeile auf Betriebsystemebene oder programmatisch über einen Aufruf aus der main()-Methode heraus. Für den Ablauf können Optionen angegeben werden, entweder auf der Kommandoebene oder programmatisch mithilfe eines OptionBuilders. Wir werden später in diesem Beitrag Beispiele dafür sehen.

Das heißt, mit JMH muss man nicht mehr machen, als die richtigen Annotationen an den geeigneten Stellen zu verwenden und passende Optionen für den Ablauf des Benchmarks anzugeben. Um alles andere kümmert sich JMH. Überlegen wir uns als Erstes, welche Probleme sich mit JMH lösen lassen.

Den vollständigen Artikel lesen Sie in der Ausgabe:

Java Magazin 2.17 - "Mehr geht immer"

Alle Infos zum Heft
579757467Microbenchmarks mit JMBH erstellen
X
- Gib Deinen Standort ein -
- or -