Javaでは、プリミティブ配列の場合、繰り返し再作成するよりもはるかに高速に配列を再利用していますか?Javaでは、プリミティブ配列の場合、繰り返し再作成するよりもはるかに高速に配列を再利用していますか?
次のスニペットは、2つのケースの比較です。(a)System.arrayCopyと(b)による配列の再利用は、集中的なループで指定された値の配列を繰り返し作成します。
public static void testArrayAllocationVsCopyPerformance() {
long time = System.currentTimeMillis();
final int length = 3000;
boolean[] array = new boolean[length];
boolean[] backup = new boolean[length];
//for (int j = 0; j < length; j++) {
// backup [j] = true;
//}
for (int i = 0; i < 10000000; i++) {
//(a). array copy
//System.arraycopy(backup, 0, array, 0, length);
//(b). reconstruct arrays
array = new boolean[length];
//for (int j = 0; j < length; j++) {
// array[j] = true;
//}
}
long millis = System.currentTimeMillis() - time;
System.out.println("Time taken: " + millis + " milliseconds.");
System.exit(0);
}
私のPCでは、(b)は平均で約2600ミリ秒かかりますが、(a)は平均で約450ミリ秒かかります。異なる値を持つ配列を再作成する場合、パフォーマンスギャップはさらに広がります。(b)平均で約3750ミリ秒、(a)は一定のままで、平均で450ミリ秒です。
上記のスニペットでは、 'boolean'が 'int'に変更された場合、結果は似ています。つまり、int配列の再利用には配列の再作成の1/3が必要です。加えて、(b)も(a)よりも読みにくくない。 (b)は、 'バックアップ'配列を必要としない(a)よりもわずかに読みにくいです。
しかし、Javaオブジェクトの作成に関するstackoverflowまたはstackexchangeに関する同様の質問の回答は、「ボトルネックになるまで最適化しないでください」、「今日のJITまたはJVMで処理することができます。 「読みやすくするためにシンプルにする」などです。そして、これらの種類の回答は、一般的に視聴者によく受け取ります。
質問:上記のパフォーマンス比較スニペットでは、短命のプリミティブ配列を使用した配列の再作成と比較して、配列のコピーがかなり速いことがわかりますか?スニペットの上に欠陥がありますか?それとも、ボトルネックなどになるまで、人々はそれを最適化してはいけませんか?
メモリの割り当てが不要なので、再利用ははるかに高速です。同じことはオブジェクト参照には適用されません。それらを再利用することは、何もしないので、いくらか意味がありません。 –
最後の文の "Or"は間違った選択です。上記のパフォーマンス比較スニペットでは、タイミングの差異がよく見えるかもしれません。ボトルネックになるまで*と*の人々はそれを最適化してはいけません。 – dasblinkenlight
実際に** 2つではなく4つの可能性があります:(再)既存の配列とarraycopyを使用します。既存の配列とfor-assignを使用する。新しい配列とarraycopyをそれに割り当てます( 'Arrays.copyOf'があなたに当てはまります)。新しい配列とfor-assignを割り当てます。パフォーマンスが重要なのは、これが多く行われた場合だけで、JITに十分に対応すればパフォーマンスが変化するということです。また、多くの配列(またはオブジェクト)を割り当てると、実際の使用ではGCの集約コストが増加しますが、1つのアイテムのエフェクトを測定することはできません。マイクロベンチマークではない5000以上の既存の回答が正しい。 –