我有seen JITC使用无符号比较来检查数组边界(测试0 <= x < LIMIT
等同于0 ≺ LIMIT
,其中≺
将数字视为无符号数量)。所以我很好奇它是否适用于0 <= x < LIMIT
形式的任意比较。
我results的benchmark非常令人困惑。我已经创建了三个表格
的实验for (int i=0; i<LENGTH; ++i) {
int x = data[i];
if (condition) result += x;
}
具有不同的条件
0 <= x
名为above
x < LIMIT
名为below
0 <= x && x < LIMIT
名为inRange
0 <= x & x < LIMIT
名为inRange2
并准备数据,以使条件成立的概率相同。
结果应该非常相似,只有above
可能会略微加快,因为它与零进行比较。即使JITC无法使用未签名的比较进行测试,above
和below
的结果仍应相似。
有谁可以解释这里发生了什么?我做错了很可能......
我在Ubuntu 2.6.32-54-generic上使用Java build 1.7.0_51-b13和i5-2400 CPU @ 3.10GHz,以防任何人关心。由于inRange
附近的inRange2
和0.00
的结果特别令人困惑,我使用more steps in this area重新运行基准。
答案 0 :(得分:0)
基准测试结果的可能变化与不同级别的CPU缓存有关。
由于正在使用原始int(s),因此没有JVM特定的缓存,正如自动装箱的Integer到原始值一样。
因此,给定data []数组的最小内存消耗,剩下的就是低级值/操作的CPU缓存。由于所描述的值的分布是基于随机值,其中条件的统计“概率”在测试中是正确的,可能的原因是,取决于值,每个测试或多或少(随机)缓存正在进行,导致更多的随机性。
此外,根据计算机的隔离(后台服务/进程),测试用例可能无法完全隔离运行。确保除核心OS功能和JVM之外的所有测试都关闭。将JVM内存设置为min / max相同,关闭所有网络进程,更新等。
答案 1 :(得分:0)
您是否测试了多次运行的结果,或者您只测试过一次这些功能?
我发现的一件事是,第一次运行for循环,JVM将解释,然后每次运行JVM都会对其进行优化。因此,前几次运行可能会获得可怕的性能,但经过几次运行后,它将接近本机性能。
我还发现循环在运行时不会被优化。我没有测试这是否仅适用于循环或整个函数。如果它只适用于循环,那么如果嵌套在内部和外部循环中,则可以获得更高的性能,并且一次处理一个数据块。如果它是整个函数,你必须将内部循环放在它自己的函数中。
还要多次运行测试,如果比较代码,您会注意到JIT如何分阶段优化代码。
对于大多数代码,这为Java提供了最佳性能。它允许它在很少运行的代码上跳过代价高昂的优化,并使代码运行得更快。但是,如果您的代码块运行一次但很长一段时间,它将变得非常慢。