繁体   English   中英

Java性能:arraylength vs iload

[英]Java performance: arraylength vs iload

for (int i=0; i<arr.length; i++) {
}

这将导致代码:

getstatic   #4;
arraylength

而以下代码:

int length = arr.length;
for (int i=0; i<length; i++) {
}

将编译为:

iload_3

两个片段之间有区别吗? 哪个代码运行得更快?

如您所见,在我的情况下,数组是静态成员。 静态和最终确切。 考虑到JIT优化,基本优化器可以感知到并将数组的长度硬编码到方法的机器代码中。 使用局部变量(第二种情况)遵循这种逻辑要困难得多,因此人们会认为第一种优化的可能性大于第二种情况。

因为它是静态的和最终的,我怀疑它可以硬编码长度,虽然我不确定它会走得那么远。 但是JIT编译器仍然可以使用第一种形式而不是第二种形式做得更好。

特别是,如果它可以检测到数组在循环内没有变化,它可以避免多次评估长度删除循环内的数组边界检查 - 它可以验证你永远不会访问外部的数组范围[0, length)

希望到现在为止,体面的JIT也会注意到第二种形式 - 但是我仍然更喜欢第一种形式的可读性,而且我希望证明它在改变那种形式之前表现不如第二种形式。

与以往一样,首先编写最易读的代码,但要根据性能要求进行测量。

两个片段之间有区别吗?

这取决于。 如果arr变量在循环体中更新,那么两个代码片段在语义上是不同的。

哪个代码运行得更快?

这是不可能的。 它取决于JIT编译器生成的本机代码,并且可以从一个补丁版本到下一个补丁版本不同。 唯一可以肯定的是转储本机代码并详细检查它,或者对代码进行基准测试。 但无论哪种方式,差异通常都太小而不值得担心。

JVM做的一个优化是避免在每次访问时检查数组的边界。 相反,它可以限制检查第一个和最后一个值。

但是,有些微优化可能会使JVM混淆,最终你会得到速度较慢的优化代码。

我在微优化时使用的形式是

for (int i = 0, length = methodCall(arr); i < length; i++) {
   // use the array.
}

我更喜欢使用最简单,最明显的解决方案,因为JVM最有可能最好地优化这个用例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM