ArrayLists比数组慢2倍

时间:2012-11-25 18:16:13

标签: java performance

我正在测试一种分子动力学算法,其中包括一个由 9数组双精度组成的粒子粒子组合来存储粒子组件(3D环境中的速度,力和位置)。 / p>

我使用5种输入尺寸测试算法:

Size (MB) Time (s)
0.06      0.36     (fits in cache L2)
0.14      1.79     (fits in cache L2)
0.60      36.86    (fits in cache L3)
1.35      182.24   (fits in cache L3)
17.38     566.55   (it only fits in RAM)

我将Particles布局从array更改为ArrayList。为了有一个连续的内存块,我创建了arrayList,其大小将占用:

ArrayList <Double> px = new ArrayList <Double>(Input_Size);

我在上述睾丸的相同条件下运行版本,结果如​​下:

Size (MB) Time (s)
0.06      0.608
0.14      2.78
0.60      57.15
1.35      299.24
17.38     1436,42

测试环境为:

AMD Opteron处理器6174,800 MHz,12 MB高速缓存L3,具有24个内核;

我的速度降低了大约2倍。这是正常的吗?不应该在两个版本中都期望几乎相同的时间,因为ArrayList在内存中像数组一样被连续分配?

编辑:

Running with the option **-XX:+PrintCompilation**

  WITH ARRAY:

 1       java.util.jar.Manifest$FastInputStream::readLine (167 bytes)
  2       sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (553 bytes)
  3       java.lang.String::hashCode (60 bytes)
  4       java.lang.String::charAt (33 bytes)
  5       sun.security.util.ManifestDigester::findSection (180 bytes)
  6       java.lang.Object::<init> (1 bytes)
  7       moldyn.random::update (104 bytes)
  8       moldyn.random::seed (80 bytes)
---   n   java.lang.StrictMath::log (static)
  9       java.lang.Math::log (5 bytes)
 10       moldyn.md::scalingVelocity (82 bytes)
 11       moldyn.Particles::distance (192 bytes)
  1%      moldyn.Particles::force @ 42 (211 bytes)
 12       moldyn.Particles::force (211 bytes)
 13       moldyn.Particles::domove (163 bytes)
 14       moldyn.Particles::domove_out (160 bytes)
  2%      moldyn.Particles::cicle_domove @ 5 (23 bytes)
 15       moldyn.Particles::update_force (49 bytes)
  3%      moldyn.Particles::cicle_forces @ 6 (27 bytes)
 16       moldyn.Particles::mkekin (141 bytes)
  4%      moldyn.Particles::cicle_mkekin @ 9 (33 bytes)
 17       moldyn.Particles::velavg (70 bytes)
  5%      moldyn.Particles::cicle_velavg @ 9 (37 bytes)
 18       moldyn.Particles::cicle_domove (23 bytes)
 19       moldyn.Particles::cicle_forces (27 bytes)
 20       moldyn.Particles::cicle_mkekin (33 bytes)
 21       moldyn.Particles::cicle_velavg (37 bytes)
36.763

WITH ArrayList <Double>....
----

  1       java.util.jar.Manifest$FastInputStream::readLine (167 bytes)
  2       sun.nio.cs.UTF_8$Decoder::decodeArrayLoop (553 bytes)
  3       java.lang.String::hashCode (60 bytes)
  4       java.lang.String::charAt (33 bytes)
  5       sun.security.util.ManifestDigester::findSection (180 bytes)
  6       java.lang.Object::<init> (1 bytes)
---   n   java.lang.System::arraycopy (static)
  7       java.lang.Number::<init> (5 bytes)
  8       java.util.ArrayList::ensureCapacity (58 bytes)
  9       java.lang.Double::valueOf (9 bytes)
 10       java.lang.Double::<init> (10 bytes)
 11       java.util.ArrayList::add (100 bytes)
 12       java.util.ArrayList::RangeCheck (48 bytes)
 13       java.util.ArrayList::set (21 bytes)
 14       moldyn.random::update (104 bytes)
 15       moldyn.random::seed (80 bytes)
---   n   java.lang.StrictMath::log (static)
 16       java.lang.Math::log (5 bytes)
 17       java.util.ArrayList::get (12 bytes)
 18       java.lang.Double::doubleValue (5 bytes)
 19       moldyn.md::scalingVelocity (120 bytes)
 20       moldyn.Particles::distance (240 bytes)
  1%      moldyn.Particles::force @ 42 (211 bytes)
 21       moldyn.Particles::force (211 bytes)
 22       moldyn.Particles::domove (337 bytes)
 23       moldyn.Particles::domove_out (292 bytes)
  2%      moldyn.Particles::cicle_domove @ 5 (23 bytes)
 24       moldyn.Particles::update_force (91 bytes)
  3%      moldyn.Particles::cicle_forces @ 6 (27 bytes)
 25       moldyn.Particles::mkekin (297 bytes)
  4%      moldyn.Particles::cicle_mkekin @ 9 (33 bytes)
 26       moldyn.Particles::velavg (118 bytes)
  5%      moldyn.Particles::cicle_velavg @ 9 (37 bytes)
 27       moldyn.Particles::cicle_domove (23 bytes)
 28       moldyn.Particles::cicle_forces (27 bytes)
 29       moldyn.Particles::cicle_mkekin (33 bytes)
 30       moldyn.Particles::cicle_velavg (37 bytes)
55.98

3 个答案:

答案 0 :(得分:6)

我有一些想法,但没有明确的答案:

  1. java.lang.Doubledouble原语不同。可能是自动装箱开销和与Double对象一起使用的额外机器会产生影响。我会比较字节代码,看看是不是这样。
  2. 听起来您double []课程中的客户隐藏了List<Double>Particle的选择。如果是这种情况,请使用数组,因为它是内部实现细节。
  3. 我会小心愚弄基准测试。
  4. 我想知道你的Particle课程是否可变。这可能会有所不同。位置,速度和力是否会连续变化并在对象中更新?

答案 1 :(得分:2)

我发现了两个潜在的问题:

1:数组周围对象的开销......

ArrayList在Array中存储可变数量的对象。这类似于创建一个对象数组,但是使用ArrayList,可以使用公开的方法轻松地从ArrayList添加和删除项目,并动态调整其大小。

这可能非常方便,但是当使用许多元素时,它比制作一个对象数组要慢。

如果您需要具有有限功能的非常灵活的Array类型的集合,则ArrayList可能是一个不错的选择。但如果你加快速度,阵列就会赢。 为避免在ArrayList内部重新复制数组,您可以使用

ensureCapacity(int requestCapacity) 

2:在你的具体情况下,从doubleDouble可能还有很多拳击/取消拳击事件,但这也会给你一些延迟。

答案 2 :(得分:1)

我建议不要在这个用例中使用数组或ArrayList。你有一个非常明显的面向对象的解决方案,它被忽略,有利于数组。

你应该使用组合来构建一个更好的结构化程序,它应该更容易阅读,并且(可能)不会导致任何额外的开销。

例如

import javax.vecmath.Vector3d;

public class Particle {

    private Vector3d velocity;
    private Vector3d force; // acceleration?
    private Vector3d position; 

    ...

}

这样您就不必担心边界检查(如同数组和ArrayList一样),也不需要担心自动装箱(如ArrayLists的情况)。您还可以获得粒子的速度,加速度和位置的每个值都恰当地命名的好处。也就是说,谁知道particle.getData()[7]指的是什么,而particle.getPosition().y指的是{{1}},这很明显。最后,Vector3d附带了一些可能有用的内置功能。<​​/ p>