Skip to content

Instantly share code, notes, and snippets.

@Groostav
Created September 6, 2023 23:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Groostav/8420ba6a61004617d6f1643b4ade9a85 to your computer and use it in GitHub Desktop.
Save Groostav/8420ba6a61004617d6f1643b4ade9a85 to your computer and use it in GitHub Desktop.
attempting to performance profile forms java switch expressions
7:10:36 p.m.: Executing 'jmh'...
> Task :compileKotlin NO-SOURCE
> Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :compileJmhKotlin NO-SOURCE
> Task :compileJmhJava UP-TO-DATE
> Task :processJmhResources NO-SOURCE
> Task :jmhClasses UP-TO-DATE
> Task :jmh
# JMH version: 1.35
# VM version: JDK 20.0.2, OpenJDK 64-Bit Server VM, 20.0.2+9
# VM invoker: C:\Program Files\Zulu\zulu-20\bin\java.exe
# VM options: --enable-preview --enable-preview -Dfile.encoding=windows-1252 -Duser.country=CA -Duser.language=en -Duser.variant
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 5 iterations, 5 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.example.SwitchBenchmarks.measureJavaIntSwitchExpression
# Run progress: 0.00% complete, ETA 00:02:00
# Fork: 1 of 1
# Warmup Iteration 1: 28.824 ops/us
# Warmup Iteration 2: 29.548 ops/us
# Warmup Iteration 3: 29.714 ops/us
# Warmup Iteration 4: 29.228 ops/us
# Warmup Iteration 5: 29.668 ops/us
Iteration 1: 29.315 ops/us
Iteration 2: 29.829 ops/us
Iteration 3: 29.736 ops/us
Iteration 4: 29.971 ops/us
Iteration 5: 29.768 ops/us
Result "org.example.SwitchBenchmarks.measureJavaIntSwitchExpression":
29.724 �(99.9%) 0.946 ops/us [Average]
(min, avg, max) = (29.315, 29.724, 29.971), stdev = 0.246
CI (99.9%): [28.778, 30.670] (assumes normal distribution)
# JMH version: 1.35
# VM version: JDK 20.0.2, OpenJDK 64-Bit Server VM, 20.0.2+9
# VM invoker: C:\Program Files\Zulu\zulu-20\bin\java.exe
# VM options: --enable-preview --enable-preview -Dfile.encoding=windows-1252 -Duser.country=CA -Duser.language=en -Duser.variant
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 5 iterations, 5 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.example.SwitchBenchmarks.measureJavaIntSwitchStatement
# Run progress: 25.00% complete, ETA 00:01:31
# Fork: 1 of 1
# Warmup Iteration 1: 29.073 ops/us
# Warmup Iteration 2: 29.402 ops/us
# Warmup Iteration 3: 28.820 ops/us
# Warmup Iteration 4: 28.138 ops/us
# Warmup Iteration 5: 28.804 ops/us
Iteration 1: 29.439 ops/us
Iteration 2: 29.482 ops/us
Iteration 3: 29.721 ops/us
Iteration 4: 29.550 ops/us
Iteration 5: 29.875 ops/us
Result "org.example.SwitchBenchmarks.measureJavaIntSwitchStatement":
29.613 �(99.9%) 0.699 ops/us [Average]
(min, avg, max) = (29.439, 29.613, 29.875), stdev = 0.182
CI (99.9%): [28.914, 30.312] (assumes normal distribution)
# JMH version: 1.35
# VM version: JDK 20.0.2, OpenJDK 64-Bit Server VM, 20.0.2+9
# VM invoker: C:\Program Files\Zulu\zulu-20\bin\java.exe
# VM options: --enable-preview --enable-preview -Dfile.encoding=windows-1252 -Duser.country=CA -Duser.language=en -Duser.variant
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 5 iterations, 5 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.example.SwitchBenchmarks.measureJavaTypeIfInstanceofElseIf
# Run progress: 50.00% complete, ETA 00:01:00
# Fork: 1 of 1
# Warmup Iteration 1: 32.371 ops/us
# Warmup Iteration 2: 32.975 ops/us
# Warmup Iteration 3: 32.449 ops/us
# Warmup Iteration 4: 33.227 ops/us
# Warmup Iteration 5: 32.538 ops/us
Iteration 1: 33.297 ops/us
Iteration 2: 33.607 ops/us
Iteration 3: 33.757 ops/us
Iteration 4: 33.529 ops/us
Iteration 5: 33.677 ops/us
Result "org.example.SwitchBenchmarks.measureJavaTypeIfInstanceofElseIf":
33.573 �(99.9%) 0.679 ops/us [Average]
(min, avg, max) = (33.297, 33.573, 33.757), stdev = 0.176
CI (99.9%): [32.894, 34.252] (assumes normal distribution)
# JMH version: 1.35
# VM version: JDK 20.0.2, OpenJDK 64-Bit Server VM, 20.0.2+9
# VM invoker: C:\Program Files\Zulu\zulu-20\bin\java.exe
# VM options: --enable-preview --enable-preview -Dfile.encoding=windows-1252 -Duser.country=CA -Duser.language=en -Duser.variant
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 5 iterations, 5 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: org.example.SwitchBenchmarks.measureJavaTypeSwitchExpression
# Run progress: 75.00% complete, ETA 00:00:30
# Fork: 1 of 1
# Warmup Iteration 1: 31.236 ops/us
# Warmup Iteration 2: 31.416 ops/us
# Warmup Iteration 3: 31.731 ops/us
# Warmup Iteration 4: 31.995 ops/us
# Warmup Iteration 5: 31.591 ops/us
Iteration 1: 31.947 ops/us
Iteration 2: 31.630 ops/us
Iteration 3: 30.647 ops/us
Iteration 4: 31.658 ops/us
Iteration 5: 31.281 ops/us
Result "org.example.SwitchBenchmarks.measureJavaTypeSwitchExpression":
31.433 �(99.9%) 1.920 ops/us [Average]
(min, avg, max) = (30.647, 31.433, 31.947), stdev = 0.499
CI (99.9%): [29.512, 33.353] (assumes normal distribution)
# Run complete. Total time: 00:02:01
REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.
NOTE: Current JVM experimentally supports Compiler Blackholes, and they are in use. Please exercise
extra caution when trusting the results, look into the generated code to check the benchmark still
works, and factor in a small probability of new VM bugs. Additionally, while comparisons between
different JVMs are already problematic, the performance difference caused by different Blackhole
modes can be very significant. Please make sure you use the consistent Blackhole mode for comparisons.
Benchmark Mode Cnt Score Error Units
SwitchBenchmarks.measureJavaIntSwitchExpression thrpt 5 29.724 � 0.946 ops/us
SwitchBenchmarks.measureJavaIntSwitchStatement thrpt 5 29.613 � 0.699 ops/us
SwitchBenchmarks.measureJavaTypeIfInstanceofElseIf thrpt 5 33.573 � 0.679 ops/us
SwitchBenchmarks.measureJavaTypeSwitchExpression thrpt 5 31.433 � 1.920 ops/us
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.3/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 2m 2s
3 actionable tasks: 1 executed, 2 up-to-date
7:12:39 p.m.: Execution finished 'jmh'.
package org.example;
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 5, time = 5)
@Measurement(iterations = 5, time = 1)
@Fork(1)
@State(Scope.Benchmark)
public class JavaJHMBenchmarks {
@State(Scope.Thread)
public static class MyState {
public final Node[] nodes = new Node[]{
new Node.FirstNodeType(0),
new Node.SecondNodetype("one"),
new Node.ThirdNodeType(2.0f),
new Node.FourthNodeType(3L)
};
@Setup(Level.Invocation)
public void reallyFastSetup(){
node = nodes[index];
index += 1;
if(index >= nodes.length) index -= nodes.length;
}
private int index;
public Node node;
public Object result;
}
@Benchmark
public void measureJavaTypeSwitchExpression(MyState state) {
// this is by far the most elegant
state.result = switch (state.node){
case Node.FirstNodeType first -> first.id(); //warning: boxing
case Node.SecondNodetype second -> second.name();
case Node.ThirdNodeType third -> third.decimal();
case Node.FourthNodeType fourth -> fourth.bits();
};
}
@Benchmark
public void measureJavaTypeIfInstanceofElseIf(MyState state){
var node = state.node;
Object result = null;
if(node instanceof Node.FirstNodeType first){
result = first.id();
}
else if (node instanceof Node.SecondNodetype second){
result = second.name();
}
else if (node instanceof Node.ThirdNodeType third){
result = third.decimal();
}
else if (node instanceof Node.FourthNodeType fourth){
result = fourth.bits();
}
state.result = result;
}
@Benchmark
public void measureJavaIntSwitchStatement(MyState state){
var node = state.node;
Object result = null;
switch(node.typeInt()){
case 0: result = ((Node.FirstNodeType) node).id(); break;
case 1: result = ((Node.SecondNodetype) node).name(); break;
case 2: result = ((Node.ThirdNodeType) node).decimal(); break;
case 3: result = ((Node.FourthNodeType) node).bits(); break;
}
state.result = result;
}
@Benchmark
public void measureJavaIntSwitchExpression(MyState state){
var node = state.node;
Object result = switch(node.typeInt()){
case 0 -> ((Node.FirstNodeType) node).id();
case 1 -> ((Node.SecondNodetype) node).name();
case 2 -> ((Node.ThirdNodeType) node).decimal();
case 3 -> ((Node.FourthNodeType) node).bits();
default -> throw new UnsupportedOperationException();
};
state.result = result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment