我们看到一种行为,当负载很轻时,JVM的性能会降低。特别是在多次运行中,在测试环境中,我们注意到当降低送入系统的订单消息的比率时,延迟会恶化约100%。下面是该问题的一些背景知识,对此我将不胜感激。
简单地说,正在研究的演示Java交易应用程序可以认为具有3个重要线程:订单接收者线程,处理器线程,交换发送器线程
订单接收器线程接收订单并将其放入处理器q。处理器线程从处理器q提取它,进行一些基本处理,然后将其放在交换q上。交换发送器线程从交换q提取并向交换发送命令。
当抽入系统的订单率从较高的数量更改为较低的数量时,从订单接收到下达订单到交易所的等待时间会恶化100%。
尝试的解决方案:
通过发送高消息率并在降低消息率之前启动系统来预热JVM中的关键代码路径:无法解决问题
分析应用程序:使用探查器,它可以在代码中显示热点,通过改进实现可以使热点提高10 -15%。但是,仅通过提高消息速率就无法获得100%的改进。
有人对此有任何见解/建议吗?这可能与线程上的调度抖动有关。
难道是在低消息速率下线程正在从核心中切换出来?
我认为可能与下面2条相关的帖子。但是,我们的症状有所不同:
中/低负载的持续等待时间需要对Linux进行特定调整。
以下是我的旧检查清单中的几点,这与具有毫秒延迟要求的组件有关。
isolcpus
从调度程序中排除专用内核taskset
将关键线程绑定到特定核心numactl
)中运行Linux调度程序和功率采样是导致低/中低延迟时间变化很大的关键因素。
默认情况下,CPU内核会在不活动时降低频率,因此,下一个内核上的下一个请求处理速度会较慢。
CPU缓存是关键性能资产,如果您的关键线程安排在不同的内核上,它将丢失其缓存数据。同样,同一内核的其他线程调度将驱逐缓存,这也会增加关键代码的延迟。
在重负载下,这些因素不太重要(频率最大化且线程忙于〜100%趋向于坚持特定的核心)。
尽管在低/中负载下,这些因素对平均延迟和高百分位数均产生负面影响(与重负载情况相比,99%可能要差几个数量级。]]
对于高吞吐量应用程序(每秒10万个请求以上),高级线程间通信方法(例如LMAX disruptor也很有用。