为什么 JVM 性能会随着负载的增加而提高?

Why does JVM performance improve with more load?

我们发现了一种行为,即当负载较轻时 JVM 的性能会下降。特别是在多次运行中,在测试环境中,我们注意到当泵入系统的订单消息速率降低时,延迟恶化了大约 100%。下面是关于这个问题的一些背景,我将不胜感激。

简单地说,正在调查的演示 Java 交易应用程序可以被认为具有 3 个重要线程: 订单接收线程, 处理器线程, 交换发射线程

订单接收线程接收订单并将其放在处理器 q 上。处理器线程从处理器 q 中获取它,进行一些基本处理并将其放在交换器 q 上。交易所发送器线程从交易所 q 中获取它并向交易所发送订单。

当输入系统的订单率从较高数字变为较低数字时,从订单接收到订单发送到交易所的延迟会恶化 100%。

尝试过的解决方案:

  1. 通过发送高消息率并在降低消息率之前启动系统来预热 JVM 中的关键代码路径: 没有解决问题

  2. 分析应用程序: 它使用探查器显示代码中的热点,通过改进实施可能会有 10 -15% 的改进。但是,仅仅通过增加消息速率获得的 100% 改善范围内没有任何改善。

有人对此有任何 insights/suggestions 吗?会不会跟线程的调度抖动有关

难道是在低消息率下,线程被从核心中切换出来了?

2 个我认为可能相关的帖子如下。但是我们的症状有点不同:

is the jvm faster under load?

low/medium 负载的一致延迟需要特定调整 Linux。

以下是我的旧检查列表中的几点,与具有毫秒延迟要求的组件相关。

  • 将 CPU 内核配置为始终 运行 和最大频率(here 是 RedHat 的文档)
  • 为您的关键应用程序线程配置专用 CPU 核心
    • 使用isolcpus从调度程序中排除专用内核
    • 使用taskset将关键线程绑定到特定核心
  • 在单个 NUMA 节点(使用 numactl)中将您的服务配置为 运行

Linux 调度程序和功率采样是 low/medium 低延迟下高延迟差异的关键因素。

默认情况下,CPU 核心在不活动时会降低频率,因此您的下一个请求在降频核心上的处理速度较慢。

CPU 缓存是关键的性能资产,如果您的关键线程被安排在不同的内核上,它将丢失其缓存数据。此外,为同一核心调度的其他线程会逐出缓存,同时增加关键代码的延迟。

在重负载下,这些因素不太重要(频率已达到最大值,线程约 100% 忙于坚持特定的核心)。

虽然在 low/medium 负载下,这些因素对平均延迟和高百分位数都有负面影响(与重负载情况相比,99 个百分位数可能更差)。

对于高吞吐量应用程序(超过 100k request/sec),高级线程间通信方法(例如 LMAX disruptor)也很有用。