Java 分析:ForkJoinPool的性能
问题 由于Fork-Join似乎是当前的热门话题,并且在很多答案中都被推荐,我想:为什么不研究一下它的实际速度呢 为了衡量这一点,我编写了一个小程序(见下面的代码),它进行一些数字相加,并使用各种参数进行分叉,包括线程数、分叉深度和分叉分布,然后测量执行时间,特别是实际计算所用的时间与分叉所用的时间 抽象答案 虽然实现得很好,但是ForkJoin是一种非常低效的任务并行化方法,因为每个fork的成本非常高。一个简单的问题优化实现可以轻松地归档99%的线程执行时间(这比使用Fork-Join度量的所有时间都要快),因此这样的实现总是比Fork-Join实现更快。此外,如果每个fork的实际任务很小,那么fork-Join实现可能比单线程线性实现慢得多 因此,Fork-Join更像是一个是否有助于代码架构的问题,因为它与其他实现相比没有任何性能优势。因此,只有在以下情况下才应使用Fork Join:Java 分析:ForkJoinPool的性能,java,multithreading,performance,fork-join,Java,Multithreading,Performance,Fork Join,问题 由于Fork-Join似乎是当前的热门话题,并且在很多答案中都被推荐,我想:为什么不研究一下它的实际速度呢 为了衡量这一点,我编写了一个小程序(见下面的代码),它进行一些数字相加,并使用各种参数进行分叉,包括线程数、分叉深度和分叉分布,然后测量执行时间,特别是实际计算所用的时间与分叉所用的时间 抽象答案 虽然实现得很好,但是ForkJoin是一种非常低效的任务并行化方法,因为每个fork的成本非常高。一个简单的问题优化实现可以轻松地归档99%的线程执行时间(这比使用Fork-Join度量的
- 性能并不重要,任务通常需要等待其他任务的结果才能继续。因此,基本上,如果Fork-Join结构大大简化了任务,而不是简单的实现
- 实际任务大大降低了分叉成本,因此损失可以忽略不计。在我的测试中,一个添加了2个值的循环必须在每个fork中至少循环10000次才能获得合理的性能
是整个计算从主线程的角度所花费的总时间Time total
是在所有分叉组合中实际计算斐波那契级数所花费的时间Time task
是线程化带来的相对收益(Time task/Time total)Time task percentage
是(设置)排列(每个叉的叉数)和(计算)的叉深spread->depth
是实际使用的线程数threads
是每个线程实际用于计算斐波那契数列的时间task time/thread
公共类测试{
静态最终int NUM_线程数=4;
静态最终整型排列=10;
静态最终整数循环=4000000;
静态最终整数计算\u N=10000;
静态最终布尔值DO_ASYNC=true;
//---
静态final long MAX_DEPTH=Math.round(Math.log(循环)/Math.log(扩展));//尝试让执行花费大约相同的时间
私有静态类任务扩展了RecursiveTask{
最终静态AtomicLong-timeExecute=新的AtomicLong(0);
最终静态AtomicLong TotalOOPS=新的AtomicLong(0);
最终长深度;
公共任务(最终长深度){
这个。深度=深度;
}
@凌驾
受保护整数计算(){
如果(深度<最大深度){
最终任务[]子任务=新任务[排列];
for(int i=0;iTime total: 8766.670 ms, time task: 1717.418 ms ( 19.59%), spread->depth: 2->26, thread#: 1, task-time/thread: 19.59%
Time total: 7872.244 ms, time task: 1421.478 ms ( 18.06%), spread->depth: 10-> 8, thread#: 1, task-time/thread: 18.06%
Time total: 7336.052 ms, time task: 1280.036 ms ( 17.45%), spread->depth: 100-> 4, thread#: 1, task-time/thread: 17.45%
Time total: 7866.777 ms, time task: 1421.488 ms ( 18.07%), spread->depth: 10-> 8, thread#: 1, task-time/thread: 18.07%
Time total: 7085.142 ms, time task: 1349.207 ms ( 19.04%), spread->depth: 10-> 8, thread#: 2, task-time/thread: 9.52%
Time total: 6580.609 ms, time task: 1476.467 ms ( 22.44%), spread->depth: 10-> 8, thread#: 4, task-time/thread: 5.61%
Time total: 12487.634 ms, time task: 5707.720 ms ( 45.71%), spread->depth: 10-> 8, thread#: 1, task-time/thread: 45.71%
Time total: 8386.855 ms, time task: 5768.881 ms ( 68.78%), spread->depth: 10-> 8, thread#: 2, task-time/thread: 34.39%
Time total: 7078.769 ms, time task: 6086.997 ms ( 85.99%), spread->depth: 10-> 8, thread#: 4, task-time/thread: 21.50%
Time total: 5941.344 ms, time task: 5228.258 ms ( 88.00%), spread->depth: 10-> 7, thread#: 1, task-time/thread: 88.00%
Time total: 3160.818 ms, time task: 5244.241 ms (165.91%), spread->depth: 10-> 7, thread#: 2, task-time/thread: 82.96%
Time total: 16301.697 ms, time task: 53351.694 ms (327.28%), spread->depth: 10-> 8, thread#: 4, task-time/thread: 81.82%
Time total: 5204.786 ms, time task: 5119.133 ms ( 98.35%), spread->depth: 10-> 6, thread#: 1, task-time/thread: 98.35%
Time total: 26033.889 ms, time task: 51084.118 ms (196.22%), spread->depth: 10-> 7, thread#: 2, task-time/thread: 98.11%
Time total: 13183.573 ms, time task: 51637.471 ms (391.68%), spread->depth: 10-> 7, thread#: 4, task-time/thread: 97.92%
Benchmark Mode Cnt Score Error Units
ThreadPoolBenchmarkFjp.fjpBenchmark thrpt 10 6873.926 ± 334.733 ops/s
ThreadPoolBenchmarkStdJdk.stdJdkBenchmark thrpt 10 3210.170 ± 170.883 ops/s
Benchmark Mode Cnt Score Error Units
ThreadPoolBenchmarkFjp.fjpBenchmark thrpt 10 9679.502 ± 1160.887 ops/s
ThreadPoolBenchmarkStdJdk.stdJdkBenchmark thrpt 10 3466.997 ± 81.594 ops/s