减少了数组访问时间,没有数组边界检查java

时间:2012-06-28 15:21:03

标签: java arrays performance

确定。我是错误计算的微基准测试的东西。如果你没有多余的时间,请不要读。

而不是

double[] my_array=new array[1000000];double blabla=0;
for(int i=0;i<1000000;i++)
{
  my_array[i]=Math.sqrt(i);//init
}

for(int i=0;i<1000000;i++)
{
  blabla+=my_array[i];//array access time is 3.7ms per 1M operation
}

我用过

public final static class my_class
{
 public static double element=0;
 my_class(double elementz)
 {
 element=elementz;
 }
}

my_class[] class_z=new my_class[1000000];
for(int i=0;i<1000000;i++)
{
class_z[i]=new my_class(Math.sqrt(i)); //instantiating array elements for later use(random-access)
}

double blabla=0;

for(int i=0;i<1000000;i++)
{
blabla+=class_z[i].element; // array access time 2.7 ms per 1M operations.
}
}

每1M循环迭代的循环开销接近0.5 ms(使用此偏移量)。

类的元素访问时间比原始数组低%25%。 问题:您是否知道更低的随机访问时间? intel 2Ghz单核java -eclipse

3 个答案:

答案 0 :(得分:2)

再次查看你的代码,我可以看到在第一个循环中你添加了1m个不同的元素。在第二个示例中,您将添加相同的static元素1次。


微基准测试的一个常见问题是您执行测试的顺序会影响结果。

例如,如果您有两个循环,则第一个循环最初不会编译为本机代码。但是经过一段时间后,整个方法将被编译,循环运行得更快。

然后你运行第二个循环,发现它是

  • 要快得多,因为它从一开始就经过优化。 (对于简单的循环)
  • 慢得多,因为它在没有任何运行时指标的情况下进(对于复杂的循环)

您需要将每个循环放在一个单独的方法中,并以相应的次数运行测试以获得可重现的结果。


在第一种情况下,循环在运行一段时间后才会进行优化。在第二种情况下,你的循环很可能在它启动时被编译。

答案 1 :(得分:1)

差异很容易解释:

  • 原始数组的内存占用量为1M * 8字节= 8MB。
  • 类阵列的内存占用量为1M * 4字节= 4MB,均指向同一实例(假设32位VM或压缩引用64位VM)。

将不同的对象放入类数组中,您将看到原始数组的表现更好。你现在正在比较橘子和苹果。

答案 2 :(得分:0)

您的基准测试和上述评估存在一些问题。首先,您的代码不会如图所示进行编译。其次,您的基准测试时间(即几毫秒)太短暂,无法与当今的高速处理器相比具有任何统计价值。第三,你将苹果与橙子进行比较(如上所述)。也就是说,你计时两个完全不同的用例:一个静态变量和一百万个变量。

我修复了你的代码并在i7-2620m上运行了几次,重复10,000 x 1,000,000次。所有结果都在+/- 1%之内,这对于这个讨论来说已经足够了。然后,我采取了所有这些运行中最快的,以便比较他们的表现。

上面,你声称第二个用例比第一个用例“低25%”。这非常不准确。

为了进行“静态”与“变量”性能比较,我改变了第一个基准来添加第999,999个平方根,就像第二个正在做的那样。第二个用例的差异仅为4.63%。

为了进行数组访问性能比较,我将第二个用例更改为“非静态”变量。第一个用例(原始数组访问)的差异大约为68.2%,这意味着第一种方式比第二种方式快得多。

(自从我25年来一直在进行绩效评估和评估以来,请随时向我提出更多有关微基准测试的信息。)