我惊了!CompletableFuture居然有性能问题!

本文探讨了Dubbo源码中CompletableFuture的使用,指出get()方法可能导致性能问题,原因是get()方法在某些JDK版本中会频繁调用`Runtime.availableProcessors`,在多处理器环境下造成性能下降。通过分析JDK的bug报告,揭示了问题的根源和解决方案,建议在特定JDK版本中避免使用get(),而是使用带超时的get()方法以提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

国庆的时候闲来无事,就随手写了一点之前说的比赛的代码,目标就是保住前 100 混个大赛的文化衫就行了。

现在还混在前 50 的队伍里面,稳的一比。

其实我觉得大家做柔性负载均衡那题的思路其实都不会差太多,就看谁能把关键的信息收集起来并利用上了。

由于是基于 Dubbo 去做的嘛,调试的过程中,写着写着我看到了这个地方:

org.apache.dubbo.rpc.protocol.AbstractInvoker#waitForResultIfSync

先看我框起来的这一行代码,aysncResult 的里面有有个 CompletableFuture ,它调用的是带超时时间的 get() 方法,超时时间是 Integer.MAX_VALUE,理论上来说效果也就等同于 get() 方法了。

从我直观上来说,这里用 get() 方法也应该是没有任何毛病的,甚至更好理解一点。

但是,为什么没有用 get() 方法呢?

其实方法上的注释已经写到原因了,就怕我这样的人产生了这样的疑问:

抓住我眼球的是这这几个单词:

have serious performance drop。

性能严重下降。

大概就是说我们必须要调用 java.util.concurrent.CompletableFuture#get(long, java.util.concurrent.TimeUnit) 而不是 get() 方法,因为 get 方法被证明会导致性能严重的下降。

对于 Dubbo 来说, waitForResultIfSync 方法,是主链路上的方法。我个人觉得保守一点说,可以说 90% 以上的请求都会走到这个方法来,阻塞等待结果。所以如果该方法如果有问题,则会影响到 Dubbo 的性能。

Dubbo 作为中间件,有可能会运行在各种不同的 JDK 版本中,对于特定的 JDK 版本来说,这个优化确实是对于性能的提升有很大的帮助。

就算不说 Dubbo ,我们用到 CompletableFuture 的时候,get() 方法也算是我们常常会用到的一个方法。

另外,这个方法的调用链路我可太熟悉了。

因为我两年前写的第一篇公众号文章就是探讨 Dubbo 的异步化改造的,《Dubbo 2.7新特性之异步化改造》

当年,这部分代码肯定不是这样的,至少没有这个提示。

因为如果有这个提示的话,我肯定第一次写的时候就注意到了。

果然,我去翻了一下,虽然图片已经很模糊了,但是还是能隐约看到,之前确实是调用的 get() 方法:

我还称之为最“骚”的一行代码。

因为这一行的代码就是 Dubbo 异步转同步的关键代码。

前面只是一个引子,本文不会去写 Dubbo 相关的知识点。

主要写写 CompletableFuture 的 get() 到底有啥问题。

放心,这个点面试肯定不考。只是你知道这个点后,恰好你的 JDK 版本是没有修复之前的,写代码的时候可以稍微注意一下。

学 Dubbo 在方法调用的地方加上一样的 NOTICE,直接把逼格拉满。等着别人问起来的时候,你再娓娓道来。

或者不经意间看到别人这样写的时候,轻飘飘的说一句:这里有可能会有性能问题,可以去了解一下。

啥性能问题?

根据 Dubbo 注释里面的这点信息,我也不知道啥问题,但是我知道去哪里找问题。

这种问题肯定在 openJDK 的 bug 列表里面记录有案,所以第一站就是来这里搜索一下关键字:

https://bugs.openjdk.java.net/projects/JDK/issues/

一般来说,都是一些陈年老 BUG,需要搜索半天才能找到自己想要的信息。

但是,这次运气好到爆棚,弹出来的第一个就是我要找的东西,简直是搞的我都有点不习惯了,这难道是传说中的国庆献礼吗,不敢想不敢想。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值