为什么?即使有“数万点”,代码也将在很短的时间内完成,并且您不会真正获得任何“并行流”。
这听起来像是一个过早优化的完美示例,您可能会使代码复杂化一些(还没有)问题,并且至少在这种情况下不太可能成为问题。
为了证明我的观点,我创建了下面的测试代码。
为了最大限度地减少 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
没有大的区别,虽然并行流看起来稍微慢一些。
另请注意,它在不到 0.3 ms的时间内完成,获得 10,000 个点。
没什么!
让我们尝试将计数从 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 运行引起的。
结论:过早的优化是不好的!!!!
在您的情况下,您实际上使情况变得更糟。