1

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

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

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

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

尝试的解决方案:

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

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

有人对此有任何见解/建议吗?它是否与线程上的调度抖动有关。

难道是在低消息率下线程正在从核心切换出来?

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

jvm在负载下更快吗?

为什么JVM需要预热?

4

1 回答 1

1

低/中负载的一致延迟需要对 Linux 进行特定调整。

以下是我的旧清单中的几点,这与具有毫秒延迟要求的组件相关。

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

Linux 调度程序和功率采样是导致低/中低延迟的高方差的关键因素。

默认情况下,如果 CPU 内核处于非活动状态,则会降低频率,因此您的下一个请求在降频内核上的处理速度较慢。

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

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

尽管在低/中负载下,这些因素对平均延迟和高百分位数都有负面影响(与重负载情况相比,99 个百分位数可能要差一个数量级)。

对于高吞吐量应用程序(超过 100k 请求/秒),高级线程间通信方法(例如LMAX中断器)也很有用。

于 2019-10-03T12:25:28.083 回答