Aeron 中这么多空闲策略选哪个?
接上文《Aeron 是什么?》https://xie.infoq.cn/article/27422063a2cadcc054187135e
Aeron 提供了一系列等待策略,一般是应用于消息订阅程序,用来定义没有消息可以处理的时候应用线程应该做什么。
1. IdleStrategy 类型
空闲策略接口定义了两个方法:
idle:空闲的动作,比如 sleep;
reset:重置内部状态
通过这两个方法就能实现不同的空闲策略。
1.1 SleepingIdleStrategy
调用 LockSupport.parkNanos(this.sleepPeriodNs) 让出一段 CPU 时间。
1.2 SleepingMillisIdleStrategy
调用 Thread.sleep(this.sleepPeriodMs) 让出一段 CPU 时间。
适用于机器资源较低或者应用逻辑复杂的场景。
LockSupport.parkNanos 和 Thread.sleep 的主要区别在于 parkNanos 不会被中断,并且性能更好。
1.3 YieldingIdleStrategy
通过调用 Thread.yield() 让出当前线程的 CPU 时间片,重新变成就绪状态,并重新竞争 CPU 调度,它可能会获取到,也有可能被其他线程获取到。
1.4 NoOpIdleStrategy
空实现,什么都不做。
这可能导致 TTSP (Time To SafePoint) 问题,可以通过添加 JVM 参数解决:-XX:CompileCommand=dontinline,org.agrona.concurrent.NoOpIdleStrategy::idle。
1.5 BusySpinIdleStrategy
通过自旋(ThreadHints.onSpinWait())来等待,因为自旋期间不会放弃 CPU 使用权,所以这种策略 CPU 占用率会非常高,适用于高吞吐,低延迟,硬件资源充足的场景。
另外这也可能导致 TTSP 问题,解决方法与上面一样。
1.6 BackoffIdleStrategy
自旋 + yield + parkNanos,在性能和 CPU 占用率之间有很好的折中,延迟不均匀,是 aeron 的默认策略。
几个核心参数:
maxSpins:最多执行几次 ThreadHints.onSpinWait();
maxYields:最多执行几次 Thread.yield();
minParkPeriodNs:parkNanos 的最短时间限制;
maxParkPeriodNs:parkNanos 的最长时间限制。
2. 测试
我们使用 Aeron Ipc 做为 Service Mesh Sidecar 的通信组件,下面测试了两个服务之间的时延情况,重点关注了 BusySpinIdleStrategy 和 BackoffIdleStrategy 两种等待策略,以下是它们的测试对比结果:
(测试固定 1000 QPS)
需要说明的是,以上的平均时延并不是 Aeron Ipc 这一步的时延,而是我们 Service Mesh sidecar 场景端到端的平均时延。
总结
从测试结果来看,如果不关心 CPU 占用率的话,使用 BusySpinIdleStrategy 或者配置一些激进的 BackoffIdleStrategy 参数,可以达到极低的时延;但是如果需要平衡 CPU 占用率那么时延会增加一些。
版权声明: 本文为 InfoQ 作者【BUG侦探】的原创文章。
原文链接:【http://xie.infoq.cn/article/41d0885f46594e90cbdba4b2b】。文章转载请联系作者。
评论