7

本次测试

        for (;;) {
            int[] a = new int[10];
            System.gc();
            long t0 = System.currentTimeMillis();
            for (int i = 0; i < 1000000; i++) {
//              int[] b =  a.clone();
                int[] b =  Arrays.copyOf(a, a.length);
            }
            System.out.println(System.currentTimeMillis() - t0);
        }

显示 Arrays.copyOf 约 50 毫秒,克隆约 160 毫秒。克隆是一种特殊的原生复制方法,为什么这么慢?

我在我的 HotSpot Client JVM 1.7.0_11-b21 上运行了测试。请注意,当数组大小增加时,clone 和 copyOf 之间的差异就会消失。

4

2 回答 2

5

我在我的系统上运行了你的代码:它们之间几乎没有区别。两者的时钟都在大约 30 毫秒。我的测试是在 OpenJDK 7 上进行的。

为了确认我也通过 Caliper 运行它,并使用更大的数组来强调实际的复制性能:

public class Performance extends SimpleBenchmark {
  final int[] source = new int[1000];

  public int timeClone(int reps) {
    int sum = 0;
    for (int i = reps; i > 0; i--)
      sum += source.clone().length;
    return sum;
  }

  public int timeCopyOf(int reps) {
    int sum = 0;
    for (int i = reps; i > 0; i--)
      sum += Arrays.copyOf(source,source.length).length;
    return sum;
  }
  public static void main(String... args) {
    Runner.main(Performance.class, args);
  }
}

结果:

 0% Scenario{vm=java, trial=0, benchmark=Clone} 2141.70 ns; σ=5416.80 ns @ 10 trials
50% Scenario{vm=java, trial=0, benchmark=CopyOf} 2168.38 ns; σ=1545.85 ns @ 10 trials

benchmark   us linear runtime
    Clone 2.14 =============================
   CopyOf 2.17 ==============================

vm: java
trial: 0

根据请求,这里的数组大小为 10:

 0% Scenario{vm=java, trial=0, benchmark=Clone} 30.07 ns; σ=2.12 ns @ 10 trials
50% Scenario{vm=java, trial=0, benchmark=CopyOf} 29.34 ns; σ=161.38 ns @ 10 trials

benchmark   ns linear runtime
    Clone 30.1 ==============================
   CopyOf 29.3 =============================
于 2013-02-06T18:23:46.593 回答
0

我找到了一篇很好的文章,解释了为什么克隆在这里很慢http://www.javaspecialists.eu/archive/Issue124.html。简而言之,这是因为 int[].clone 仅使用 Object.clone 并且此方法在复制数组之前进行了两次检查:

1.检查实例是普通对象还是数组。

2.检查数组是基元还是对象。

我将这些检查添加到 Arrays.copyOf 测试

        for (int i = 0; i < 1000000; i++) {
            Class cls = a.getClass();
            if (cls.isArray() && !cls.getComponentType().isAssignableFrom(Object.class)) {
                int[] b = Arrays.copyOf(a, a.length);
            }
        }

并且测试表明 clone 和 Arrays.copyOf 之间没有区别。如果它是阵列克隆的专用版本,将会很快。

于 2013-02-10T05:12:12.843 回答