Java Math.log()的死代码消除在JMH示例中如何工作
任何试图利用JMH框架创建一些有意义的测试的人都会遇到JMH示例测试 (). 当我们浏览它们的时候,我们被死代码元素(JMHSample_08_DeadCode.java)绊倒了 摘录:Java Math.log()的死代码消除在JMH示例中如何工作,java,intrinsics,microbenchmark,jmh,Java,Intrinsics,Microbenchmark,Jmh,任何试图利用JMH框架创建一些有意义的测试的人都会遇到JMH示例测试 (). 当我们浏览它们的时候,我们被死代码元素(JMHSample_08_DeadCode.java)绊倒了 摘录: private double x = Math.PI; @Benchmark public void baseline() { // do nothing, this is a baseline } @Benchmark public void measureWrong() { // This is w
private double x = Math.PI;
@Benchmark
public void baseline() {
// do nothing, this is a baseline
}
@Benchmark
public void measureWrong() {
// This is wrong: result is not used, and the entire computation is optimized out.
Math.log(x);
}
MeasureError()的测量值约为
与基线测试相同。因为
从未使用Math.log()。因此,热点编译器
将消除死代码。好的,明白了,但是编译器如何决定可以删除Math.log()
当我们仔细查看测试时,我们注意到Math.log()是一个本机方法。
而本机调用则进入操作系统并执行相应的lib。对吗?
这导致我们假设,如果不使用本机调用的返回值并且它们不执行io操作,则编译器可以消除本机调用
我们想知道,如果驻留在操作系统中某个地方并处理来自java世界的本机调用的lib
不提供返回值,但执行io操作(如日志记录)。
这些指令会被彻底删除吗
为了证明我们的假设,我们用一个简单的JMH测试和一个本机调用重构了场景。
我们编译了三个c-native LIB来执行:
- 在编译时,热点检查Math.log()的内在实现(在jdk中?)是否存在,并用该代码替换Math.log()
- 之后,第二个检查发生在热点关注方法返回值的地方。根据这个结果,HotSpot决定完全取消Math.log()调用
实际上,Math.log是一个内在的。这意味着,JIT知道它,并用一组预定义的机器指令代替它。此外,本机指令不会被jit消除,因为它无法证明它们没有副作用。Android可能仍然将其原生方法视为内在方法。感谢您提供详细而有用的答案。缺乏关于本机代码中可能的副作用的知识解释了为什么本机调用没有被消除。