[JAVA] Ich habe versucht, die Geschwindigkeit von Graal VM mit JMH zu messen und zu vergleichen

Umgebung

Grobes Problem der vorherigen Messung

[Vorheriger Artikel](https://qiita.com/kinshotomoya/items/39a821dd6a6a52202c0a#%E5%AE%9F%E9%9A%9B%E3%81%AB%E4%BD%BF%E3%81%A3 % E3% 81% A6% E3% 81% BF% E3% 82% 8B) und der Geschwindigkeitsvergleich zwischen GraalVm und Standard-JVM wurde durchgeführt.

Da jedoch die Kompilierungszeit, die Aufwärmzeit und die reine Ausführungszeit gemischt und gemessen wurden, war es nicht möglich, einen reinen Geschwindigkeitsvergleich von Graal selbst durchzuführen.

Dieses Mal möchte ich die Geschwindigkeit von Graal von GraalVM und C2-Compiler von Standard-JVM vergleichen.

Daher unterscheiden wir zwischen Kompilierung (Generierung von Klassendateien), Aufwärmen und reiner Ausführungszeit und vergleichen die reine Ausführungszeit.

Spezifische Probleme

1. Die Kompilierungszeit (Generierung von Klassendateien) wurde ebenfalls berücksichtigt.

Generieren Sie bei der Ausführung mit sbt vor der Ausführung eine Mischklassendatei und messen Sie dann.

$ sbt compile
$ sbt run

2. Die Aufwärmverarbeitung und die Nachkompilierungsverarbeitung wurden in einem Durcheinander gemessen.

Wie ich in diesem Artikel geschrieben habe, führt die JVM zuerst die Klassendatei auf dem Interprinter aus (erwärmt sie) und sammelt die für die Kompilierung erforderlichen Informationen. Der JIT-Compiler dient zum Kompilieren der Zielmethode.

** Um die reine Ausführungsgeschwindigkeit des Graal- oder C2-Compilers zu messen, müssen Sie die Zielmethode aufwärmen-> die Geschwindigkeit nach der Kompilierung messen. ** **.

Laut diesem Buch beträgt der Schwellenwert für den Wechsel vom Interprinter des JIT-Compilers zum JIT-Compiler das 8000-fache. Mit anderen Worten, wenn Sie eine Methode 8000 Mal oder öfter ausführen (aufwärmen), wird die Methode vom JIT-Compiler kompiliert, sodass Sie die Geschwindigkeit des kompilierten Codes messen können.

Geschwindigkeit mit JMH messen

Das letzte Mal wurde die Messung mit dem Befehl / usr / bin / time durchgeführt. Da es jedoch nicht möglich ist, einen reinen Geschwindigkeitsvergleich durchzuführen, wird JMH verwendet, um genaue Werte zu erhalten.

Es gibt sbt library, also habe ich es benutzt.

Code zum Messen

Ein Programm, das englische Sätze aus einer Textdatei liest und die 10 am häufigsten verwendeten Wörter ausspuckt.

├── resources
│   └── GraalTest.txt
└── scala
    └── graal
        └── Performance.scala

Textdatei. Ich habe einen passenden englischen Satz mitgebracht.

Graal.txt


When people talk about Japan, they would always think about how innovative and technological this country gets! Or how pretty and neat the country is! Last but not the least, fashion, Cosplay and hype beast were always a big thing in the city of Japan. Coming to Japan with the intention of tourism would have been a great experience. Different culture. You can find a lot of unique things they sell in Japan! But as you live in Japan, you interact with the locals and everything doesn’t seem the way you thought of Japan.

Die Größe beträgt 525B.

$ ll
-rw-r--r--  1 kinsho  staff   525B  6 14 10:18 GraalTest.txt

In der JMH-Bibliothek können Messoptionen mit Anmerkungen angegeben werden. Es wurde wie folgt eingestellt.

Performance.scala



package graal

import java.util.concurrent.TimeUnit

import org.openjdk.jmh.annotations._

import scala.annotation.tailrec
import scala.io.BufferedSource

//Geben Sie die Anzahl der Gabeln an
//Der Standardwert ist 5
@Fork(1)
@Warmup(iterations = 1, batchSize = 10000)
@Measurement(iterations = 30, batchSize = 10000)
//Messen Sie die Ausführungszeit pro Ausführung
@BenchmarkMode(Array(Mode.SingleShotTime))
//Maßeinheit ist ms
@OutputTimeUnit(TimeUnit.MILLISECONDS)
class GraalTest {

  //Zielen Sie auf diese Methode ab
  @Benchmark
  def run = {
    val fileName: String = "GraalTest.txt"
    val encode: String = "UTF-8"
    val source: BufferedSource = scala.io.Source.fromResource(fileName)
    val lines: Iterator[String] = source.getLines()
    val sortedTextList = lines.toList.mkString(" ").split(" ").sorted.toList
    val value = createMap(sortedTextList)
    val top10Words = value.toList.sortBy(_._2).reverse.take(10)
  }

  private def createMap(wordList: List[String]): Map[String, Long] = {
    @tailrec
    def loop(list: List[String], acc: Map[String, Long]): Map[String, Long] = {
      list match {
        case head :: tail if acc.isEmpty => {
          loop(tail, acc + (head -> 1L))
        }
        case head :: tail => {
          acc.get(head) match {
            case Some(value) => {
              loop(tail, acc.updated(head, value + 1L))
            }
            case None => {
              loop(tail, acc + (head -> 1L))
            }
          }
        }
        case head :: Nil => {
          acc.get(head) match {
            case Some(value) => {
              acc.updated(head, value + 1L)
            }
            case None => {
              acc + (head -> 1L)
            }
          }
        }
        case Nil => acc
      }
    }
    loop(wordList, Map.empty[String, Long])
  }
}


Auf Standard-JVM ausführen

Zuerst kompilieren

sbt:jitCompiler> jmh:compile
[info] Compiling 3 Scala sources to /Users/kinsho/workspace/loginfrastructure/jitCompiler/target/scala-2.13/classes ...
...
[info] Compiling 5 Java sources to /Users/kinsho/workspace/loginfrastructure/jitCompiler/target/scala-2.13/classes ...
[success] Total time: 5 s, completed 2020/06/14 12:08:28

Eigentlich ausführen. An [info] # VM-Version: JDK 1.8.0_232, OpenJDK 64-Bit-Server-VM, 25.232-b09 können Sie erkennen, dass sie mit der Standard-JVM ausgeführt wird.

sbt:jitCompiler> jmh:run
[info] running (fork) org.openjdk.jmh.Main
[info] # JMH version: 1.21
[info] # VM version: JDK 1.8.0_232, OpenJDK 64-Bit Server VM, 25.232-b09
[info] # VM invoker: /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/bin/java
[info] # VM options: <none>
[info] # Warmup: 1 iterations, single-shot each, 10000 calls per op
[info] # Measurement: 30 iterations, single-shot each, 10000 calls per op
[info] # Timeout: 10 min per iteration
[info] # Threads: 1 thread
[info] # Benchmark mode: Single shot invocation time
[info] # Benchmark: graal.GraalTest.run
[info] # Run progress: 0.00% complete, ETA 00:00:00
[info] # Fork: 1 of 1
[info] # Warmup Iteration   1: 1075.011 ms/op
[info] Iteration   1: 555.518 ms/op
[info] Iteration   2: 634.679 ms/op
[info] Iteration   3: 552.381 ms/op
[info] Iteration   4: 687.170 ms/op
[info] Iteration   5: 538.699 ms/op
[info] Iteration   6: 537.693 ms/op
[info] Iteration   7: 622.123 ms/op
[info] Iteration   8: 801.559 ms/op
[info] Iteration   9: 611.831 ms/op
[info] Iteration  10: 567.022 ms/op
[info] Iteration  11: 590.506 ms/op
[info] Iteration  12: 666.859 ms/op
[info] Iteration  13: 564.290 ms/op
[info] Iteration  14: 552.446 ms/op
[info] Iteration  15: 713.195 ms/op
[info] Iteration  16: 781.514 ms/op
[info] Iteration  17: 685.628 ms/op
[info] Iteration  18: 570.931 ms/op
[info] Iteration  19: 557.543 ms/op
[info] Iteration  20: 559.926 ms/op
[info] Iteration  21: 677.823 ms/op
[info] Iteration  22: 551.438 ms/op
[info] Iteration  23: 564.687 ms/op
[info] Iteration  24: 560.043 ms/op
[info] Iteration  25: 553.672 ms/op
[info] Iteration  26: 548.359 ms/op
[info] Iteration  27: 777.705 ms/op
[info] Iteration  28: 794.434 ms/op
[info] Iteration  29: 917.850 ms/op
[info] Iteration  30: 553.160 ms/op
[info] Result "graal.GraalTest.run":
[info]   N = 30
[info]   mean =    628.356 ±(99.9%) 67.159 ms/op
[info]   Histogram, ms/op:
[info]     [ 500.000,  550.000) = 3
[info]     [ 550.000,  600.000) = 14
[info]     [ 600.000,  650.000) = 3
[info]     [ 650.000,  700.000) = 4
[info]     [ 700.000,  750.000) = 1
[info]     [ 750.000,  800.000) = 3
[info]     [ 800.000,  850.000) = 1
[info]     [ 850.000,  900.000) = 0
[info]     [ 900.000,  950.000) = 1
[info]   Percentiles, ms/op:
[info]       p(0.0000) =    537.693 ms/op
[info]      p(50.0000) =    568.977 ms/op
[info]      p(90.0000) =    793.142 ms/op
[info]      p(95.0000) =    853.890 ms/op
[info]      p(99.0000) =    917.850 ms/op
[info]      p(99.9000) =    917.850 ms/op
[info]      p(99.9900) =    917.850 ms/op
[info]      p(99.9990) =    917.850 ms/op
[info]      p(99.9999) =    917.850 ms/op
[info]     p(100.0000) =    917.850 ms/op
[info] # Run complete. Total time: 00:00:26
[info] REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
[info] why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
[info] experiments, perform baseline and negative tests that provide experimental control, make sure
[info] the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
[info] Do not assume the numbers tell you what you want them to tell.
[info] Benchmark      Mode  Cnt    Score    Error  Units
[info] GraalTest.run    ss   30  628.356 ± 67.159  ms/op
[success] Total time: 26 s, completed 2020/06/14 12:26:25

Ergebnisse mit Standard-JVM

Die Ergebnisse werden schlampig beschrieben, aber zusammenfassend:

** Aufwärmzeit: 1075.011 ms / op ** ** Reine Geschwindigkeit: 628,356 ms / op **

ms / op ist eine Einheit, die ausdrückt, wie lange es gedauert hat, die Zielmethode einmal auszuführen. Da die Aufwärmzeit länger dauert als die reine Geschwindigkeit, können Sie auch sehen, dass sie nach 10.000 Aufwärmvorgängen normal kompiliert wird.

Führen Sie auf GraalVM aus

Diesmal der Favorit, gemessen mit GraalVM! Zuerst kompilieren.

sbt:jitCompiler> jmh:compile
[info] Compiling 3 Scala sources to /Users/kinsho/workspace/loginfrastructure/jitCompiler/target/scala-2.13/classes ...
...
[info] Compiling 5 Java sources to /Users/kinsho/workspace/loginfrastructure/jitCompiler/target/scala-2.13/classes ...
[success] Total time: 5 s, completed 2020/06/14 12:18:06

Lauf.


sbt:jitCompiler> jmh:run
Processing 9 classes from /Users/kinsho/workspace/loginfrastructure/jitCompiler/target/scala-2.13/classes with "reflection" generator
Writing out Java source to /Users/kinsho/workspace/loginfrastructure/jitCompiler/target/scala-2.13/src_managed/jmh and resources to /Users/kinsho/workspace/loginfrastructure/jitCompiler/target/scala-2.13/resource_managed/jmh
[info] running (fork) org.openjdk.jmh.Main
[info] # JMH version: 1.21
[info] # VM version: JDK 1.8.0_252, OpenJDK 64-Bit Server VM GraalVM CE 20.1.0, 25.252-b09-jvmci-20.1-b02
[info] # VM invoker: /Library/Java/JavaVirtualMachines/graalvm-ce-java8-20.1.0/Contents/Home/jre/bin/java
[info] # VM options: <none>
[info] # Warmup: 1 iterations, single-shot each, 10000 calls per op
[info] # Measurement: 30 iterations, single-shot each, 10000 calls per op
[info] # Timeout: 10 min per iteration
[info] # Threads: 1 thread
[info] # Benchmark mode: Single shot invocation time
[info] # Benchmark: graal.GraalTest.run
[info] # Run progress: 0.00% complete, ETA 00:00:00
[info] # Fork: 1 of 1
[info] # Warmup Iteration   1: 1012.169 ms/op
[info] Iteration   1: 546.073 ms/op
[info] Iteration   2: 584.707 ms/op
[info] Iteration   3: 547.958 ms/op
[info] Iteration   4: 662.077 ms/op
[info] Iteration   5: 549.202 ms/op
[info] Iteration   6: 490.277 ms/op
[info] Iteration   7: 620.376 ms/op
[info] Iteration   8: 780.583 ms/op
[info] Iteration   9: 576.626 ms/op
[info] Iteration  10: 508.686 ms/op
[info] Iteration  11: 543.451 ms/op
[info] Iteration  12: 589.145 ms/op
[info] Iteration  13: 515.498 ms/op
[info] Iteration  14: 524.002 ms/op
[info] Iteration  15: 717.083 ms/op
[info] Iteration  16: 839.723 ms/op
[info] Iteration  17: 523.987 ms/op
[info] Iteration  18: 519.271 ms/op
[info] Iteration  19: 525.304 ms/op
[info] Iteration  20: 530.935 ms/op
[info] Iteration  21: 634.322 ms/op
[info] Iteration  22: 545.711 ms/op
[info] Iteration  23: 513.338 ms/op
[info] Iteration  24: 518.737 ms/op
[info] Iteration  25: 519.130 ms/op
[info] Iteration  26: 575.139 ms/op
[info] Iteration  27: 745.525 ms/op
[info] Iteration  28: 774.832 ms/op
[info] Iteration  29: 830.160 ms/op
[info] Iteration  30: 549.396 ms/op
[info] Result "graal.GraalTest.run":
[info]   N = 30
[info]   mean =    596.708 ±(99.9%) 68.925 ms/op
[info]   Histogram, ms/op:
[info]     [400.000, 450.000) = 0
[info]     [450.000, 500.000) = 1
[info]     [500.000, 550.000) = 16
[info]     [550.000, 600.000) = 4
[info]     [600.000, 650.000) = 2
[info]     [650.000, 700.000) = 1
[info]     [700.000, 750.000) = 2
[info]     [750.000, 800.000) = 2
[info]     [800.000, 850.000) = 2
[info]   Percentiles, ms/op:
[info]       p(0.0000) =    490.277 ms/op
[info]      p(50.0000) =    548.580 ms/op
[info]      p(90.0000) =    780.008 ms/op
[info]      p(95.0000) =    834.463 ms/op
[info]      p(99.0000) =    839.723 ms/op
[info]      p(99.9000) =    839.723 ms/op
[info]      p(99.9900) =    839.723 ms/op
[info]      p(99.9990) =    839.723 ms/op
[info]      p(99.9999) =    839.723 ms/op
[info]     p(100.0000) =    839.723 ms/op
[info] # Run complete. Total time: 00:00:25
[info] REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
[info] why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
[info] experiments, perform baseline and negative tests that provide experimental control, make sure
[info] the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
[info] Do not assume the numbers tell you what you want them to tell.
[info] Benchmark      Mode  Cnt    Score    Error  Units
[info] GraalTest.run    ss   30  596.708 ± 68.925  ms/op
[success] Total time: 26 s, completed 2020/06/14 12:22:50

Ergebnisse mit GraalVm

Die Ergebnisse werden auch diesmal schlampig beschrieben, aber zusammenfassend:

** Aufwärmzeit: 1012,169 ms / op ** ** Reine Ausführungszeit: 596.708 ms / op **

Gesamtergebnis

Als Ergebnis der Messung wurde festgestellt, dass Graal schneller war. (Wenn diese Messmethode korrekt ist, scheint es mehr Punkte zu geben, die berücksichtigt werden müssen.)

Referenz

Recommended Posts

Ich habe versucht, die Geschwindigkeit von Graal VM mit JMH zu messen und zu vergleichen
Ich habe versucht, die Infrastrukturtechnologie der Ingenieure heutzutage mit dem Kochen zu vergleichen.
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit spiritueller Technik zu erhöhen
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
Ich habe versucht, das Problem der "mehrstufigen Auswahl" mit Ruby zu lösen
Ich habe versucht, mit Docker eine Plant UML Server-Umgebung zu erstellen
Ich habe versucht, den Betrieb des gRPC-Servers mit grpcurl zu überprüfen
Ich habe versucht, die Methoden von Java String und StringBuilder zusammenzufassen
Ich habe versucht, die Ergebnisse vor und nach der Date-Klasse mit einer geraden Zahl auszudrücken
Ich habe versucht, die wichtigsten Punkte des gRPC-Designs und der Entwicklung zusammenzufassen
Ich habe versucht, CSV mit Outsystems zu lesen und auszugeben
05. Ich habe versucht, die Quelle von Spring Boot zu löschen
Ich habe MySQL 5.7 mit Docker-Compose gestartet und versucht, eine Verbindung herzustellen
Ich habe versucht, die Kapazität von Spring Boot zu reduzieren
Ich habe versucht, den Betrieb der http-Anfrage (Put) mit dem Talented API Tester zu überprüfen
Ich habe versucht, den Mechanismus von Emscripten mit einem deutschen Löser zu untersuchen
Ich habe versucht, dies und das von Spring @ Transactional zu überprüfen
Ich habe JAX-RS ausprobiert und mir das Verfahren notiert
Ich habe versucht, eine Umgebung mit WSL2 + Docker + VSCode zu erstellen
Stellen Sie sicher, dass Sie das Java compareTo-Ergebnis mit 0 vergleichen
Sazae's Janken Ich habe versucht, den theoretischen Wert und den gemessenen Wert der Wahrscheinlichkeit derselben Hand 5 Mal hintereinander mit Ruby zu überprüfen
Ich habe versucht, mit Java zu interagieren
Ich habe versucht, die Methode zu erklären
[Für Swift-Anfänger] Ich habe versucht, den chaotischen Layoutzyklus von ViewController und View zusammenzufassen
Ich möchte mit Kotlin und Java zum vorherigen Bildschirm zurückkehren!
Ich habe versucht, das Problem des Google Tech Dev Guide zu lösen
Ich habe versucht, die verwendeten Methoden zusammenzufassen
Ich habe versucht, mit Web Assembly zu beginnen
Ich habe versucht, das Iterator-Muster zu implementieren
Ich habe versucht, die Stream-API zusammenzufassen
Ich möchte Bilder mit REST Controller von Java und Spring anzeigen!
[Ruby] Ich möchte nur den Wert des Hash und nur den Schlüssel extrahieren
Ich habe versucht, das Problem der Tribonacci-Sequenz in Ruby mit Wiederholung zu lösen.
Ich möchte das Argument der Annotation und das Argument der aufrufenden Methode an den Aspekt übergeben
Ich habe versucht, den CPU-Kern mit Ruby voll auszunutzen
Ich habe versucht, die Grammatik von R und Java zu übersetzen [Von Zeit zu Zeit aktualisiert]
Immerhin wollte ich den Inhalt von MySQL mit Docker in der Vorschau anzeigen ...
Ich habe versucht, den Ablauf bei der Bildanalyse mit Vision Framework und Core ML herauszufinden
Ich habe versucht, AdoptOpenJDK 11 (11.0.2) mit dem Docker-Image zu überprüfen
Ich habe versucht, die Federbeinkonfiguration mit Coggle zu verwalten
Ich habe versucht, mit HCE-F von Android eine Funktion zu implementieren, die Felica Lite entspricht
[Rails] Ich habe versucht, die Version von Rails von 5.0 auf 5.2 zu erhöhen
Ich habe versucht, Anmeldeinformationen mit JMX zu verwalten
Ich habe versucht, die Sitzung in Rails zu organisieren
Was ich versucht habe, als ich alle Felder einer Bohne bekommen wollte
Ich habe versucht, grafana und postgres [docker-compose] zu verknüpfen
Ich habe auch Web Assembly mit Nim und C ausprobiert
Ich habe die Eigenschaften von Java und .NET verglichen
C # (Grund der Kapselung)
Ich möchte den Inhalt der Absicht var_dump
Ich habe versucht, JavaFX und Spring Framework zu verknüpfen.
Ich habe versucht, Tomcat so einzustellen, dass das Servlet ausgeführt wird.
Ich habe versucht, eine Webanwendung voller Fehler mit Spring Boot zu klonen