なんで?「数万ポイント」でも、コードは非常に短い時間で完了し、「並列ストリーム」では実際には何も得られません。
これは、時期尚早の最適化の完璧な例のように思えます。この場合、(まだ) 問題ではなく、問題になる可能性が低いもののコードを複雑にする可能性があります。
私の主張を証明するために、以下のテスト コードを作成しました。
GC 実行の影響を最小限に抑えるために、このコードを-Xms10g -Xmx10g
で実行し、明示的な呼び出しを追加したgc()
ので、テスト実行は「白紙の状態」で実行されました。
いつものように、パフォーマンス テストは JIT の最適化やその他の要因の影響を受けるため、ウォームアップ ループが用意されています。
public static void main(String[] args) {
Random rnd = new Random();
List<Point3D> input = new ArrayList<>();
for (int i = 0; i < 10_000; i++)
input.add(new Point3D(rnd.nextDouble(), rnd.nextDouble(), rnd.nextDouble()));
for (int i = 0; i < 100; i++) {
test1(input);
test2(input);
}
for (int i = 0; i < 10; i++) {
long start1 = System.nanoTime();
test1(input);
long end1 = System.nanoTime();
System.gc();
long start2 = System.nanoTime();
test2(input);
long end2 = System.nanoTime();
System.gc();
System.out.printf("%.6f %.6f%n", (end1 - start1) / 1_000_000d, (end2 - start2) / 1_000_000d);
}
}
private static List<Double> test1(List<Point3D> input) {
List<Double> list = new ArrayList<>();
for (Point3D point : input) {
list.add(point.getX());
list.add(point.getY());
list.add(point.getZ());
}
return list;
}
private static List<Double> test2(List<Point3D> input) {
return input.stream().parallel()
.flatMap(s -> Stream.of(s.getX(), s.getY(), s.getZ()))
.collect(Collectors.toList());
}
結果
0.355267 0.392904
0.205576 0.260035
0.193601 0.232378
0.194740 0.290544
0.193601 0.238365
0.243497 0.276286
0.200728 0.243212
0.197022 0.240646
0.192175 0.239790
0.198162 0.279708
並列ストリームは少し遅いように見えますが、大きな違いはありません。また、10,000 ポイントの場合、0.3 ミリ秒未満
で完了することにも注意してください。
何でもありません!
カウントを 10,000 から 10,000,000 に増やしてみましょう (ウォームアップをスキップ):
433.716847 972.100743
260.662700 693.263850
250.699271 736.744653
250.486281 813.615375
249.722716 714.296997
254.704145 796.566859
254.713840 829.755767
253.368331 959.365322
255.016928 973.306254
256.072177 1047.562090
現在、並列ストリームの明確な劣化があります。3倍遅いです。これは、余分な GC 実行が原因である可能性があります。
結論: 時期尚早の最適化は良くない!!!!
あなたの場合、あなたは実際にそれを悪化させました。