Java可以使用无符号比较进行一般范围内测试吗?

时间:2014-02-19 05:24:56

标签: java performance unsigned

我有seen JITC使用无符号比较来检查数组边界(测试0 <= x < LIMIT等同于0 ≺ LIMIT,其中将数字视为无符号数量)。所以我很好奇它是否适用于0 <= x < LIMIT形式的任意比较。

resultsbenchmark非常令人困惑。我已经创建了三个表格

的实验
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无法使用未签名的比较进行测试,abovebelow的结果仍应相似。

有谁可以解释这里发生了什么?我做错了很可能......

更新

我在Ubuntu 2.6.32-54-generic上使用Java build 1.7.0_51-b13和i5-2400 CPU @ 3.10GHz,以防任何人关心。由于inRange附近的inRange20.00的结果特别令人困惑,我使用more steps in this area重新运行基准。

2 个答案:

答案 0 :(得分:0)

基准测试结果的可能变化与不同级别的CPU缓存有关。

由于正在使用原始int(s),因此没有JVM特定的缓存,正如自动装箱的Integer到原始值一样。

因此,给定data []数组的最小内存消耗,剩下的就是低级值/操作的CPU缓存。由于所描述的值的分布是基于随机值,其中条件的统计“概率”在测试中是正确的,可能的原因是,取决于值,每个测试或多或少(随机)缓存正在进行,导致更多的随机性。

此外,根据计算机的隔离(后台服务/进程),测试用例可能无法完全隔离运行。确保除核心OS功能和JVM之外的所有测试都关闭。将JVM内存设置为min / max相同,关闭所有网络进程,更新等。

答案 1 :(得分:0)

您是否测试了多次运行的结果,或者您只测试过一次这些功能?

我发现的一件事是,第一次运行for循环,JVM将解释,然后每次运行JVM都会对其进行优化。因此,前几次运行可能会获得可怕的性能,但经过几次运行后,它将接近本机性能。

我还发现循环在运行时不会被优化。我没有测试这是否仅适用于循环或整个函数。如果它只适用于循环,那么如果嵌套在内部和外部循环中,则可以获得更高的性能,并且一次处理一个数据块。如果它是整个函数,你必须将内部循环放在它自己的函数中。

还要多次运行测试,如果比较代码,您会注意到JIT如何分阶段优化代码。

对于大多数代码,这为Java提供了最佳性能。它允许它在很少运行的代码上跳过代价高昂的优化,并使代码运行得更快。但是,如果您的代码块运行一次但很长一段时间,它将变得非常慢。