Java-调用静态方法与手动内联-性能开销


问题内容

我对是否应该手动内联一些性能敏感算法中称为100k-1百万次的小型方法感兴趣。

首先,我认为通过不进行内联会产生一些开销,因为JVM必须确定是否内联此方法(甚至不能这样做)。

但是,前几天,我用静态方法调用替换了此手动内联代码,并发现性能得到了提高。那怎么可能?这是否表明实际上没有任何开销,而让JVM按其“意愿”内联实际上可以提高性能?还是这在很大程度上取决于平台/架构?

(发生性能提升的示例是用int t = a[i]; a[i] = a[j]; a[j] = t;静态方法调用替换数组swapping()swap(int[] a, int i, int j)。没有性能差异的另一示例是当我内联10个内联方法时,被称为1000000次。)


问题答案:

我看过类似的东西。“手动内联”并不一定会更快,结果程序可能太复杂而无法让优化程序进行分析。

在您的示例中,让我们做出一些疯狂的猜测。当您使用swap()方法时,JVM可能能够分析方法主体,并得出结论,由于i和j不变,尽管有4个数组访问,但仅需要2个范围检查而不是4。t不需要局部变量,JVM可以使用2个寄存器来完成工作,而无需涉及t堆栈上的读/写操作。

稍后,swap()的主体被内联到调用方方法中。那是在先前的优化之后,因此保存仍然存在。调用者方法主体甚至有可能证明i和j始终在范围内,因此剩余的2个范围检查也将被丢弃。

现在,在手动内联版本中,优化器必须立即分析整个程序,变量太多,动作太多,可能无法证明保存范围检查或消除局部变量是安全的t。在最坏的情况下,此版本可能会花费6个以上的内存访问来执行交换,这是
巨大的 开销。即使只读取1个额外的内存,它仍然非常引人注目。

当然,我们没有理由相信手动进行“概述”总是更好,即提取一些小方法,希望它会对优化器有所帮助。

-

我了解到的是,忘记手动进行微优化。不是我不关心微性能的提高,不是我一直信任JVM的优化。就是我绝对不知道该怎么做,弊大于弊。所以我放弃了。