【发布时间】:2024-03-08 19:50:01
【问题描述】:
我想比较两个Java8流终端操作reduce()和collect()的并行性能。
让我们看看下面的Java8并行流示例:
import java.math.BigInteger;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import static java.math.BigInteger.ONE;
public class StartMe {
static Function<Long, BigInteger> fac;
static {
fac = x -> x==0? ONE : BigInteger.valueOf(x).multiply(fac.apply(x - 1));
}
static long N = 2000;
static Supplier<BigInteger[]> one() {
BigInteger[] result = new BigInteger[1];
result[0] = ONE;
return () -> result;
}
static BiConsumer<BigInteger[], ? super BigInteger> accumulator() {
return (BigInteger[] ba, BigInteger b) -> {
synchronized (fac) {
ba[0] = ba[0].multiply(b);
}
};
}
static BiConsumer<BigInteger[], BigInteger[]> combiner() {
return (BigInteger[] b1, BigInteger[] b2) -> {};
}
public static void main(String[] args) throws Exception {
long t0 = System.currentTimeMillis();
BigInteger result1 = Stream.iterate(ONE, x -> x.add(ONE)).parallel().limit(N).reduce(ONE, BigInteger::multiply);
long t1 = System.currentTimeMillis();
BigInteger[] result2 = Stream.iterate(ONE, x -> x.add(ONE)).parallel().limit(N).collect(one(), accumulator(), combiner());
long t2 = System.currentTimeMillis();
BigInteger result3 = fac.apply(N);
long t3 = System.currentTimeMillis();
System.out.println("reduce(): deltaT = " + (t1-t0) + "ms, result 1 = " + result1);
System.out.println("collect(): deltaT = " + (t2-t1) + "ms, result 2 = " + result2[0]);
System.out.println("recursive: deltaT = " + (t3-t2) + "ms, result 3 = " + result3);
}
}
它计算 n!使用一些 - 诚然奇怪 ;-) - 算法。
然而,性能结果令人惊讶:
reduce(): deltaT = 44ms, result 1 = 3316275...
collect(): deltaT = 22ms, result 2 = 3316275...
recursive: deltaT = 11ms, result 3 = 3316275...
一些备注:
- 我必须同步
accumulator(),因为它并行访问同一个数组。 - 我预计
reduce()和collect()会产生相同的性能,但reduce()比collect()慢约 2 倍,即使collect()必须同步! - 最快的算法是顺序和递归算法(这可能表明并行流管理的巨大开销)
没想到reduce()的表现会比collect()的差。为什么会这样?
【问题讨论】:
-
@resueman 我建议查看 JMH 框架。它有一个很好的教程。 openjdk.java.net/projects/code-tools/jmh
标签: java performance lambda java-8 java-stream