JMH基准测试中使用@Param注解导致性能大幅下降的原因咨询
JMH使用@Param后性能暴跌的原因解析
这事儿其实是JVM即时编译器(JIT)的优化逻辑在搞鬼,我给你掰扯清楚:
1. 硬编码参数时的激进优化
当你硬编码array.toBinaryArray2(0)时,JVM的JIT编译器能在编译阶段就识别出这个参数是编译期常量。它会直接把toBinaryArray2(0)的计算结果提前算好,甚至可能把整个方法调用都内联、消除——说白了,你的基准测试其实没在执行真实的toBinaryArray2逻辑,只是在空转或者执行一个已经被优化成常量返回的操作,所以才会出现每秒20亿次的夸张吞吐量,这其实是个“失真”的结果。
2. @Param带来的参数不确定性
换成@Param({"0"})之后,arg变成了类的成员变量。哪怕你只传了一个固定值0,JMH的机制会让JVM认为这个参数是可能变化的(毕竟@Param设计的初衷就是支持多参数测试,JVM不会假设它是常量)。这时候JIT没办法做常量折叠和激进的内联优化,必须真实执行toBinaryArray2(arg)的完整逻辑,所以测出的4.8亿次/秒才是这个方法真实的性能水平。
验证你的猜测
你可以做个小实验验证这个结论:
- 在硬编码版本里,把参数改成一个非编译期常量,比如:
这时候测出的性能应该会和@Param版本接近,因为JVM同样没办法把arg当成常量优化。private int arg = 0; // 不是final,也不是硬编码在方法调用里 @Benchmark public void testMethod() { array.toBinaryArray2(arg); }
简单来说,你之前的硬编码版本测的不是方法真实性能,而是JIT优化后的空转性能;@Param版本才是真实反映方法执行效率的结果。
内容的提问来源于stack exchange,提问作者Argamidon
相关产品推荐
相关产品推荐

