【发布时间】:2014-10-27 21:52:11
【问题描述】:
在 Iterable 上使用使用 spliterator() 创建的流时,我遇到了性能问题。即,像StreamSupport.stream(integerList.spliterator(), true)。想通过正常的收藏来证明这一点。请参阅下面的一些基准测试结果。
问题: 为什么从可迭代创建的并行流比从 ArrayList 或 IntStream 创建的流慢得多?
从一个范围
public void testParallelFromIntRange() {
long start = System.nanoTime();
IntStream stream = IntStream.rangeClosed(1, Integer.MAX_VALUE).parallel();
System.out.println("Is Parallel: "+stream.isParallel());
stream.forEach(ParallelStreamSupportTest::calculate);
long end = System.nanoTime();
System.out.println("ParallelStream from range Takes : " + TimeUnit.MILLISECONDS.convert((end - start),
TimeUnit.NANOSECONDS) + " milli seconds");
}
平行:真
ParallelStream 范围需要:490 毫秒
来自可迭代对象
public void testParallelFromIterable() {
Set<Integer> integerList = ContiguousSet.create(Range.closed(1, Integer.MAX_VALUE), DiscreteDomain.integers());
long start = System.nanoTime();
Stream<Integer> stream = StreamSupport.stream(integerList.spliterator(), true);
System.out.println("Is Parallel: " + stream.isParallel());
stream.forEach(ParallelStreamSupportTest::calculate);
long end = System.nanoTime();
System.out.println("ParallelStream from Iterable Takes : " + TimeUnit.MILLISECONDS.convert((end - start),
TimeUnit.NANOSECONDS) + " milli seconds");
}
平行:真
来自 Iterable 的 ParallelStream 需要:12517 毫秒
还有这么简单的计算方法。
public static Integer calculate(Integer input) {
return input + 2;
}
【问题讨论】:
-
ContinguousSet实际上有正确的spliterator吗? Guava 没有针对 Java 8 进行优化,而 JDK 显然是。 -
ContiguousSet.spliterator()是否返回一个大小的拆分器,或者一个未知大小的拆分器?这可能会影响数据在线程之间的拆分方式。您可以使用Spliterators.spliterator(Iterator, long, int)根据迭代器和集合的大小创建拆分器。 -
Iterable 在第二个示例中在哪里发挥作用?如果其中有一个,请注意 Iterable 本质上是顺序的,因为对元素的唯一访问是通过
hasNext/next。
标签: java parallel-processing java-8 java-stream