在调用外部接口时通过 CompletableFuture.supplyAsync
异步调用,该方法默认将任务提交到全局唯一的 ForkJoinPool,而它的并行度可以受 java.util.concurrent.ForkJoinPool.common.parallelism
影响。
本实验的目的是探究在异步请求快响应(~= 1ms)时,并行度对整体性能的影响。
真实场景:
当然由于接受并发请求,同时会接收多个请求,暂不纳入考虑。bench 代码如下:
List<Future> futures = new ArrayList<>(); for(int i=0; i<N; i++) { final int x = i; futures.add(CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } bh.consume(x); return x; })); } for (Future future: futures) { future.get(); }
java -jar target/benchmarks.jar -i 5 -bs 50 -f 3
实验结果如下图:
parallelism = 1
时,ForkJoinPool 会为每个提交的任务创建一个线程 parallelism = 2
,此时最多运行两个线程,预期的时间为 1 * 200 50 / 2 = 5000ms
实际开销 6610
,多出的猜测是线程创建和切换 parallelism > 200
,也没办法达到完全并行(1ms)的状态。 大致结论:并行度越大效果越好,但 overhead 也会越来越大。
详细实验结果参见: Gist: CompletableFuture.supplyAsync profile