【问题标题】:Java 8 Concurrent Hash Map get Performance/AlternativeJava 8 Concurrent Hash Map 获得性能/替代方案
【发布时间】:2015-11-24 18:23:48
【问题描述】:

我有一个高吞吐量低延迟应用程序(3000 请求/秒,每个请求 100 毫秒),我们大量使用 Java 8 ConcurrentHashMap 来执行查找。通常这些地图由一个后台线程更新,多个线程从这些地图中读取。

我看到了性能瓶颈,在分析时我发现 ConcurrentHashMap.get 是热点并且占用了大部分时间。

在另一种情况下,我看到 ConcurrentHashMap.computeIfAbsent 是热点,尽管映射函数的延迟非常小,并且配置文件显示 computeIfAbsent 花费 90% 的时间执行自身,并且执行映射的时间非常少 -功能。

我的问题是有什么办法可以提高性能?我有大约 80 个线程同时从 CHM 读取数据。

【问题讨论】:

  • @AmmSokun computeIfAbsent 在读取和潜在计算值之前悲观地锁定。在 32+ 核心机器上,在竞争下似乎确实更快,但在其他方面,乐观读取要快得多。当读取成功的可能性很高时尤其如此,例如在缓存中。当它确实翻转时,差异就不那么明显了,因此预筛选是一个净收益。
  • 在 jdk 8 中,该参数只是尺寸提示,不再使用了
  • 其实问题是"3000 Request/Sec"。每个请求执行多少个 CHM 方法调用?由于每个请求花费 100 毫秒,因此 CHM 调用应该是其中的一小部分,或者每个请求必须超过 1 个。换句话说,这个问题提供了非常模糊的数据,你甚至没有包括你的分析器输出。
  • @AmmSokun 变量f 表示找到的else 块,桶链使用synchronized (f)。 Doug Lea recommends 为小于 32 路机器的预筛选优化,但必须展望未来,该优化时间太短而无法采用。
  • 另一段有趣的代码chm.put(key, System.currentTimeMillis(),这是在每个请求的平均大小为 100 的循环中完成的,我认为chm.get(key).setTime(System.currentTimeMillis()) 会更好。伙计们怎么说?

标签: performance java-8 concurrenthashmap


【解决方案1】:

我有大约 80 个线程同时从 CHM 读取数据。

最简单的做法是

  • 如果你有一个 CPU 绑定的进程,那么活动线程不要多于你的 CPU,否则只会增加开销,如果这些线程在不运行时持有锁,因为你有太多线程,它真的会没有帮助。
  • 增加分区数。您将希望拥有至少 4 倍的段/分区数量,并且您有访问单个映射的线程。但是,由于缓存一致性的工作方式,如果您使用超过 40 个线程访问 CHM,您将在 CHM 中出现奇怪的行为。我建议使用更高效的数据结构来实现更高程度的并发。在 Java 8 中,concurrencyLevel 是一个提示,但它比保留默认的初始化大小 16 更好。
  • 不要花太多时间在 CHM 上。找到一种在不占用共享资源的情况下完成有用工作的方法,您的线程将更高效地运行。

如果您在低延迟系统中看到任何延迟,恕我直言,您有问题。

【讨论】:

  • `如果你使用超过 40 个线程访问 CHM,你会在 CHM 中得到奇怪的行为` 你能详细说明一下吗?会有什么行为?毕竟 CHM 是为并发访问而设计的,不是吗?此外,除非有很多作者,否则我认为大量线程 阅读 没有任何问题。
  • @SvetlinZarev 好点,阅读应该不是问题。在具有大量 CPU 的系统上,当您有超过 40 个活动线程访问同一个 CHM 时,我发现 CHM 存在可伸缩性问题。这很可能是硬件而不是软件问题,因为机器使用了多个插槽。当我们可以在一个套接字上有 40 个线程时,我怀疑问题会消失。
  • 谢谢@Peter!! QQ:我发现的另一件事是使用 CHM 键作为 java.util.TimeZone get 比使用 CHM 键作为键需要更长的时间。对此有什么想法吗?是否与碰撞有关?
  • @AmmSokun SimpleTimeZone 的哈希码很差,但也可能是因为它不可比。 Java 8 中的 HashMap 使用 Tree 作为 String 键,但使用链表用于像 TimeZone 这样的类的冲突。
  • 但是 ZoneInfo 类呢? TimeZone.getInstance() 返回一个 ZoneInfo 类 obj。
猜你喜欢
  • 1970-01-01
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多