当前位置: 首页 > 网络应用技术

性能是坑|使用Java 8 concurrenthashmap的Computeifabsent

时间:2023-03-09 11:18:25 网络应用技术

  让我们先看一下段落。当使用代码时,可能会像这样编写:

  有一种方法可以简化Java 8中的上述代码:

  除了上述写作方式的简单性外,如果您使用它,您还可以确保在同时调用以确保原子质的情况下不会重复调用该方法。

  但是,不久前,当执行Apache shardingsphere-proxy时,当连接到shardingsphere代理的基准测试端子的数量相对较高时,问题就遇到了一个问题。在异步profiler的帮助下,发现computeifabsent of computeifabsent of computeifabsent of computeifabsent of。Java 8 ConcurrentHashmap在性能中累积。

  不了解Apache shardingsphere的读者可以参考https://github.com/apache/shardingsphere。

  考虑到当时的压力测试现象是基准SQL(终端)的数量越高,简单而反复执行了新订单业务中较新的SQL执行延迟。位于不满。考虑到代理代码级别是否有瓶颈,在压力测试中,代理JVM对其进行了采样。

  您可以参考https://github.com/jvm-profiling-tools/async-profiler,我还考虑将来写一些相关文章。

  使用想法读取样本获得的JFR文件,并在我看到事件时看到超过300万次!根据堆栈,查找shardingsphere的守则,以下是摘录:

  Java#l65

  上面的代码将在每个代理与数据库交互之前执行,即通过代理执行CRUD操作的唯一方法,其中只有两种类型,它们是Harmoniousthe Thread称为同一键。

  我的理解是,如果存在操作,则操作没有修改。只是直接得到。事实是什么?看看该方法的实现(JDK是Oracle 8U311)。

  根据我对源代码的理解,即使存在密钥,当我进入密钥时,我将输入代码。与不锁定操作相比,这会影响性能吗?google来到相应的主题并发现了一些内容:https://bugs.openjdk.java.net/browse/jdk-8161372这个问题早已提到了它,并且它也在JDK 9中进行了处理。正式发布了JDK 17。

  在JDK 8仍在流行的当前环境中,我们需要考虑如何避免上述问题,因此相应的处理方法是诞生的:https://github.com/apache/shardings/shardingsphere/pull/13275/files

  Java#L76-L80

  每次从地图获得价值时,都会使用它进行检查。使用该值之前不存在值。由于它可以确保原子性,因此无需添加或进行多次检查(例如它)。

  问题解决了?

  可以看出,两种方法在性能方面有许多不同。直接电话的性能为每秒一百万。首先,检查的性能为每秒1000亿级,这只是对第16个线程的测试。在资源条款中,CPU利用率已保持在约20%;测试期间的CPU利用率为100%。

  JDK 17测试结果似乎略低于性能,但性能至少相同的数量。在两种情况下操作期间的CPU已满。