在调用外部接口时通过 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