Last active
December 12, 2025 11:30
-
-
Save xuwei-k/1775f8046f76e66d54e124e91804c431 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // a2/src/main/scala/Bench.scala | |
| package example | |
| import org.openjdk.jmh.annotations.Benchmark | |
| class Bench { | |
| inline final def limit: Int = 100 | |
| @Benchmark | |
| def release8(): Int = { | |
| var i = 0 | |
| var sum = 0 | |
| while (i < limit) { | |
| sum += Release8.f( | |
| i % 2 == 0, | |
| i.toByte, | |
| i.toShort, | |
| i, | |
| i, | |
| i.toFloat, | |
| i, | |
| i.toString, | |
| i.toChar | |
| ).length | |
| i += 1 | |
| } | |
| sum | |
| } | |
| @Benchmark | |
| def release11(): Int = { | |
| var i = 0 | |
| var sum = 0 | |
| while (i < limit) { | |
| sum += Release11.f( | |
| i % 2 == 0, | |
| i.toByte, | |
| i.toShort, | |
| i, | |
| i, | |
| i.toFloat, | |
| i, | |
| i.toString, | |
| i.toChar | |
| ).length | |
| i += 1 | |
| } | |
| sum | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| sbt.version=1.11.7 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| val common = Def.settings( | |
| scalaVersion := "3.7.4", | |
| ) | |
| def src(objectName: String): String = { | |
| Seq( | |
| s"""package example | |
| object ${objectName} {""", | |
| """ | |
| def f( | |
| x1: Boolean, | |
| x2: Byte, | |
| x3: Short, | |
| x4: Int, | |
| x5: Long, | |
| x6: Float, | |
| x7: Double, | |
| x8: String, | |
| x9: Char, | |
| ): String = { | |
| val a1 = s" $x1 $x2 $x3 $x4 $x5 $x6 $x7 $x8 $x9 " | |
| s" $x1 $a1 $x2 $a1 $x3 $a1 $x4 $a1 $x5 $a1 $x6 $a1 $x7 $a1 $x8 $a1 $x9 " | |
| } | |
| } | |
| """ | |
| ).mkString("\n") | |
| } | |
| def sourceGen(objectName: String) = | |
| Compile / sourceGenerators += task { | |
| val f = (Compile / sourceManaged).value / s"${objectName}.scala" | |
| IO.write(f, src(objectName)) | |
| Seq(f) | |
| } | |
| val a1 = project | |
| .settings( | |
| scalacOptions += "-release:11", | |
| sourceGen("Release11"), | |
| common | |
| ) | |
| val a2 = project | |
| .enablePlugins(JmhPlugin) | |
| .settings( | |
| scalacOptions += "-release:8", | |
| sourceGen("Release8"), | |
| common | |
| ) | |
| .dependsOn(a1) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public java.lang.String f(boolean, byte, short, int, long, float, double, java.lang.String, char); | |
| descriptor: (ZBSIJFDLjava/lang/String;C)Ljava/lang/String; | |
| flags: (0x0001) ACC_PUBLIC | |
| Code: | |
| stack=19, locals=13, args_size=10 | |
| 0: iload_1 | |
| 1: iload_2 | |
| 2: iload_3 | |
| 3: iload 4 | |
| 5: lload 5 | |
| 7: fload 7 | |
| 9: dload 8 | |
| 11: aload 10 | |
| 13: iload 11 | |
| 15: invokedynamic #52, 0 // InvokeDynamic #0:makeConcatWithConstants:(ZBSIJFDLjava/lang/String;C)Ljava/lang/String; | |
| 20: astore 12 | |
| 22: iload_1 | |
| 23: aload 12 | |
| 25: iload_2 | |
| 26: aload 12 | |
| 28: iload_3 | |
| 29: aload 12 | |
| 31: iload 4 | |
| 33: aload 12 | |
| 35: lload 5 | |
| 37: aload 12 | |
| 39: fload 7 | |
| 41: aload 12 | |
| 43: dload 8 | |
| 45: aload 12 | |
| 47: aload 10 | |
| 49: aload 12 | |
| 51: iload 11 | |
| 53: invokedynamic #57, 0 // InvokeDynamic #1:makeConcatWithConstants:(ZLjava/lang/String;BLjava/lang/String;SLjava/lang/String;ILjava/lang/String;JLjava/lang/String;FLjava/lang/String;DLjava/lang/String;Ljava/lang/String;Ljava/lang/String;C)Ljava/lang/String; | |
| 58: areturn |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public java.lang.String f(boolean, byte, short, int, long, float, double, java.lang.String, char); | |
| descriptor: (ZBSIJFDLjava/lang/String;C)Ljava/lang/String; | |
| flags: (0x0001) ACC_PUBLIC | |
| Code: | |
| stack=3, locals=13, args_size=10 | |
| 0: new #38 // class java/lang/StringBuilder | |
| 3: dup | |
| 4: ldc #39 // int 10 | |
| 6: invokespecial #42 // Method java/lang/StringBuilder."<init>":(I)V | |
| 9: ldc #44 // String | |
| 11: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 14: iload_1 | |
| 15: invokevirtual #51 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; | |
| 18: ldc #44 // String | |
| 20: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 23: iload_2 | |
| 24: invokevirtual #54 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; | |
| 27: ldc #44 // String | |
| 29: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 32: iload_3 | |
| 33: invokevirtual #54 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; | |
| 36: ldc #44 // String | |
| 38: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 41: iload 4 | |
| 43: invokevirtual #54 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; | |
| 46: ldc #44 // String | |
| 48: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 51: lload 5 | |
| 53: invokevirtual #57 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder; | |
| 56: ldc #44 // String | |
| 58: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 61: fload 7 | |
| 63: invokevirtual #60 // Method java/lang/StringBuilder.append:(F)Ljava/lang/StringBuilder; | |
| 66: ldc #44 // String | |
| 68: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 71: dload 8 | |
| 73: invokevirtual #63 // Method java/lang/StringBuilder.append:(D)Ljava/lang/StringBuilder; | |
| 76: ldc #44 // String | |
| 78: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 81: aload 10 | |
| 83: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 86: ldc #44 // String | |
| 88: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 91: iload 11 | |
| 93: invokevirtual #66 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder; | |
| 96: ldc #44 // String | |
| 98: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 101: invokevirtual #70 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; | |
| 104: astore 12 | |
| 106: new #38 // class java/lang/StringBuilder | |
| 109: dup | |
| 110: ldc #71 // int 18 | |
| 112: invokespecial #42 // Method java/lang/StringBuilder."<init>":(I)V | |
| 115: ldc #44 // String | |
| 117: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 120: iload_1 | |
| 121: invokevirtual #51 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; | |
| 124: ldc #44 // String | |
| 126: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 129: aload 12 | |
| 131: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 134: ldc #44 // String | |
| 136: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 139: iload_2 | |
| 140: invokevirtual #54 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; | |
| 143: ldc #44 // String | |
| 145: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 148: aload 12 | |
| 150: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 153: ldc #44 // String | |
| 155: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 158: iload_3 | |
| 159: invokevirtual #54 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; | |
| 162: ldc #44 // String | |
| 164: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 167: aload 12 | |
| 169: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 172: ldc #44 // String | |
| 174: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 177: iload 4 | |
| 179: invokevirtual #54 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; | |
| 182: ldc #44 // String | |
| 184: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 187: aload 12 | |
| 189: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 192: ldc #44 // String | |
| 194: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 197: lload 5 | |
| 199: invokevirtual #57 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder; | |
| 202: ldc #44 // String | |
| 204: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 207: aload 12 | |
| 209: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 212: ldc #44 // String | |
| 214: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 217: fload 7 | |
| 219: invokevirtual #60 // Method java/lang/StringBuilder.append:(F)Ljava/lang/StringBuilder; | |
| 222: ldc #44 // String | |
| 224: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 227: aload 12 | |
| 229: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 232: ldc #44 // String | |
| 234: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 237: dload 8 | |
| 239: invokevirtual #63 // Method java/lang/StringBuilder.append:(D)Ljava/lang/StringBuilder; | |
| 242: ldc #44 // String | |
| 244: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 247: aload 12 | |
| 249: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 252: ldc #44 // String | |
| 254: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 257: aload 10 | |
| 259: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 262: ldc #44 // String | |
| 264: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 267: aload 12 | |
| 269: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 272: ldc #44 // String | |
| 274: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 277: iload 11 | |
| 279: invokevirtual #66 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder; | |
| 282: ldc #44 // String | |
| 284: invokevirtual #48 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
| 287: invokevirtual #70 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; | |
| 290: areturn |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.8") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| a2 main > Jmh/run -i 5 -wi 5 -f1 -t1 | |
| [info] running (fork) org.openjdk.jmh.Main -i 5 -wi 5 -f1 -t1 | |
| [info] # JMH version: 1.37 | |
| [info] # VM version: JDK 21.0.9, OpenJDK 64-Bit Server VM, 21.0.9+10-LTS | |
| [info] # VM invoker: /Users/kenji/.sdkman/candidates/java/21.0.9-amzn/bin/java | |
| [info] # VM options: <none> | |
| [info] # Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable) | |
| [info] # Warmup: 5 iterations, 10 s each | |
| [info] # Measurement: 5 iterations, 10 s each | |
| [info] # Timeout: 10 min per iteration | |
| [info] # Threads: 1 thread, will synchronize iterations | |
| [info] # Benchmark mode: Throughput, ops/time | |
| [info] # Benchmark: example.Bench.release11 | |
| [info] # Run progress: 0.00% complete, ETA 00:03:20 | |
| [info] # Fork: 1 of 1 | |
| [info] # Warmup Iteration 1: 42147.412 ops/s | |
| [info] # Warmup Iteration 2: 41367.195 ops/s | |
| [info] # Warmup Iteration 3: 42604.134 ops/s | |
| [info] # Warmup Iteration 4: 42821.657 ops/s | |
| [info] # Warmup Iteration 5: 43027.407 ops/s | |
| [info] Iteration 1: 43065.151 ops/s | |
| [info] Iteration 2: 43077.944 ops/s | |
| [info] Iteration 3: 43320.732 ops/s | |
| [info] Iteration 4: 43110.252 ops/s | |
| [info] Iteration 5: 43427.503 ops/s | |
| [info] Result "example.Bench.release11": | |
| [info] 43200.316 ±(99.9%) 631.171 ops/s [Average] | |
| [info] (min, avg, max) = (43065.151, 43200.316, 43427.503), stdev = 163.913 | |
| [info] CI (99.9%): [42569.146, 43831.487] (assumes normal distribution) | |
| [info] # JMH version: 1.37 | |
| [info] # VM version: JDK 21.0.9, OpenJDK 64-Bit Server VM, 21.0.9+10-LTS | |
| [info] # VM invoker: /Users/kenji/.sdkman/candidates/java/21.0.9-amzn/bin/java | |
| [info] # VM options: <none> | |
| [info] # Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable) | |
| [info] # Warmup: 5 iterations, 10 s each | |
| [info] # Measurement: 5 iterations, 10 s each | |
| [info] # Timeout: 10 min per iteration | |
| [info] # Threads: 1 thread, will synchronize iterations | |
| [info] # Benchmark mode: Throughput, ops/time | |
| [info] # Benchmark: example.Bench.release8 | |
| [info] # Run progress: 50.00% complete, ETA 00:01:40 | |
| [info] # Fork: 1 of 1 | |
| [info] # Warmup Iteration 1: 28674.787 ops/s | |
| [info] # Warmup Iteration 2: 28865.500 ops/s | |
| [info] # Warmup Iteration 3: 28848.062 ops/s | |
| [info] # Warmup Iteration 4: 28784.413 ops/s | |
| [info] # Warmup Iteration 5: 28649.526 ops/s | |
| [info] Iteration 1: 28838.453 ops/s | |
| [info] Iteration 2: 28788.429 ops/s | |
| [info] Iteration 3: 28600.508 ops/s | |
| [info] Iteration 4: 28948.695 ops/s | |
| [info] Iteration 5: 28965.212 ops/s | |
| [info] Result "example.Bench.release8": | |
| [info] 28828.259 ±(99.9%) 567.306 ops/s [Average] | |
| [info] (min, avg, max) = (28600.508, 28828.259, 28965.212), stdev = 147.328 | |
| [info] CI (99.9%): [28260.953, 29395.566] (assumes normal distribution) | |
| [info] # Run complete. Total time: 00:03:20 | |
| [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] NOTE: Current JVM experimentally supports Compiler Blackholes, and they are in use. Please exercise | |
| [info] extra caution when trusting the results, look into the generated code to check the benchmark still | |
| [info] works, and factor in a small probability of new VM bugs. Additionally, while comparisons between | |
| [info] different JVMs are already problematic, the performance difference caused by different Blackhole | |
| [info] modes can be very significant. Please make sure you use the consistent Blackhole mode for comparisons. | |
| [info] Benchmark Mode Cnt Score Error Units | |
| [info] Bench.release11 thrpt 5 43200.316 ± 631.171 ops/s | |
| [info] Bench.release8 thrpt 5 28828.259 ± 567.306 ops/s | |
| [success] Total time: 201 s (0:03:21.0), completed Dec 12, 2025, 11:26:24 AM |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment