Java 为什么JMH对不同的实现显示相同的结果?
JMH为不同的方法显示相同的结果,无论这些方法是否包含任何代码 示例1:要测试的空方法Java 为什么JMH对不同的实现显示相同的结果?,java,jvm,jmh,Java,Jvm,Jmh,JMH为不同的方法显示相同的结果,无论这些方法是否包含任何代码 示例1:要测试的空方法 public class MyBenchmark { public static void main(String[] args) throws Exception { org.openjdk.jmh.Main.main(args); } @Fork(value = 1, warmups = 0) @Benchmark @BenchmarkMode(M
public class MyBenchmark {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
@Fork(value = 1, warmups = 0)
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5)
public String run() {
return "done";
}
}
运行此代码的结果是1e-8 s/op
示例2:有一些工作要做的方法:
public class MyBenchmark {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000000; i++) {
list.add(i);
}
org.openjdk.jmh.Main.main(args);
}
private static List<Integer> list = new ArrayList<>();
@Fork(value = 1, warmups = 0)
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5)
public String run() {
List<Integer> copy = new ArrayList<>();
for (Integer item : list) {
copy.add(item);
}
return "done";
}
}
公共类MyBenchmark{
公共静态void main(字符串[]args)引发异常{
对于(int i=0;i<10000000;i++){
列表.添加(i);
}
org.openjdk.jmh.Main.Main(args);
}
私有静态列表=新的ArrayList();
@叉子(值=1,预热=0)
@基准
@基准模式(模式平均时间)
@预热(迭代次数=5次)
公共字符串run(){
列表副本=新建ArrayList();
用于(整数项:列表){
副本。添加(项目);
}
返回“完成”;
}
}
结果是一样的:1e-8 s/op
因此,基准显然不起作用。可能有什么问题?您使用的时间刻度不正确-每次操作秒数。对于你的无操作测试来说,它似乎太大了。只需将以下参数
@OutputTimeUnit(TimeUnit.NANOSECONDS)
添加到测试中:
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;
public class MyBenchmark {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
@Fork(value = 1, warmups = 0)
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public String run() {
return "done";
}
}
结果如下:
# Run complete. Total time: 00:00:25
Benchmark Mode Cnt Score Error Units
MyBenchmark.run avgt 20 5.390 ± 0.264 ns/op
关于第二个示例,它包含几乎所有可能的问题/陷阱:
- 死代码elimintaion-JVM足够智能,可以检测循环而不会产生副作用,并将其从方法体中删除
- 测量错误
- 不正确的初始化-JMH具有特殊注释
和设置
,用于正确的基准初始化状态
为了了解微基准标记的所有可能问题,请阅读。您使用的时间刻度不正确-每次操作秒数。对于你的无操作测试来说,它似乎太大了。只需将以下参数
@OutputTimeUnit(TimeUnit.NANOSECONDS)
添加到测试中:
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;
public class MyBenchmark {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
@Fork(value = 1, warmups = 0)
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public String run() {
return "done";
}
}
结果如下:
# Run complete. Total time: 00:00:25
Benchmark Mode Cnt Score Error Units
MyBenchmark.run avgt 20 5.390 ± 0.264 ns/op
关于第二个示例,它包含几乎所有可能的问题/陷阱:
- 死代码elimintaion-JVM足够智能,可以检测循环而不会产生副作用,并将其从方法体中删除
- 测量错误
- 不正确的初始化-JMH具有特殊注释
和设置
,用于正确的基准初始化状态
为了了解微基准标记的所有可能问题,请阅读。当您将任何实际工作放在该方法中时,会有什么不同吗?使其无法工作。在我的例子中,空方法的工作时间甚至比“重”方法更长……当你在这个方法中放入任何实际工作时,会有什么不同吗?使其无法工作。在我的例子中,空方法的工作时间甚至比“重”方法更长。。。