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 を使用し、このメソッドは配列をコピーする前に 2 つのチェックを行うためです。

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 に答える