Alibaba Cloud Linux 2 是阿里云操作系统团队基于开源 Linux 4.19 LTS 版本打造的一款针对云应用场景的下一代 Linux OS 发行版。在首次推出一年后,阿里云操作系统团队对外正式发布了Alibaba Cloud Linux 2 LTS 版本。LTS 版本的发布是一个重要的里程碑,标志着阿里云操作系统团队将为 Alibaba Cloud Linux 2 提供长期技术支持、稳定的更新和更好的服务,为 Alibaba Cloud Linux 2 的客户提供更多保障。

由于Alibaba Cloud Linux 2主要是运行在阿里云平台上,所以我们对虚拟化进行了大量优化,今天给大家分享的Guest Idle Halt Polling特性就是其中之一,它重点解决一类 频繁睡眠和唤醒 的业务在虚拟机形态下的性能问题。

问题定义

一般虚拟机部署形态有两种,一种是独享型虚拟机,一种是共享型虚拟机。独享型虚拟机是指vCPU独享一个物理CPU的虚拟机,阿里云售卖的通用实例都是独享型的。共享型虚拟机是指多个vCPU共享一个物理CPU的虚拟机,阿里云的共享实例就属于这种类型。这里借用一下阿里云的官方文档。

共享型实例采用非绑定CPU调度模式。每个vCPU会被随机分配到任何空闲CPU超线程上,不同实例vCPU会争抢物理CPU资源,并导致高负载时计算性能波动不稳定,有可用性SLA保证,但无性能SLA保证。与企业级实例相比,共享型实例在资源利用上侧重于资源性能的共享,所以无法保证实例计算性能的稳定,但是成本更低。 --	(摘自阿里云ECS共享型实例文档)

此外,自建虚拟机的客户(如阿里云ECS专有宿主机DDH的客户,或本地服务器上使用Alibaba Cloud Linux 2虚拟机的客户),除了服务器固有成本以及虚拟机资源利用率外,也同样关注宿主机资源利用率、能耗等成本。因此自建“共享型实例”的形态以及面临的问题和ECS共享型实例类似,本文用“共享虚拟机”简称上述三类场景

共享虚拟机采用 虚拟机+宿主机 的两级进程调度方案,以保障实例间的公平性。但操作系统提供的两级方案并不完美,尤其在一类业务中严重失效,使得成本并未显著降低的情况下性能却明显下降。这一类业务的特征是会发生频繁睡眠和唤醒(例如巨量使用futex的业务、大量进程间通信的业务)。

性能 or 成本? both!

0.png

使用蒙德里安式几何抽象诠释世界经典电影《九品芝麻官》的经典场景:“我全都要”。(大误

“性能-成本”折中是数据中心、云计算中“亘古不变”的话题。如何在选择最优化性能方案的同时考量基于单位性能产生的收益呢?阿里云通过背后强大的资源调度、共享、QoS等技术,保障了ECS共享型实例有较高性能。同时由于高资源利用率,使得阿里云能够为客户提供很低的定价。具体我们是如何做到的呢?

Alibaba Cloud Linux 2提供的Guest Idle Halt Polling技术,有效解决了这类业务的折中,通过很小的边际成本,保障了业务性能。上述三种场景中,客户的性能都能得到保障。在成本上,专有宿主机,本地服务器通过提高资源利用率可以直接为客户节省成本;而ECS共享实例则依靠节省的成本使得阿里云可以提供很低的定价。“我全都要”不是梦。

经常空闲也会让性能变差? —— 问题分析

对比宿主机上,当物理CPU空闲时,它将依据用户喜好和负载情况进入不同节能模式。

而在两级进程调度中,当虚拟机的vCPU空闲时,将执行HLT指令退出到宿主机中,并触发上下文切换。宿主机将决定在物理CPU上调度其它进程或vCPU,或是进入节能模式。如图,

1.png

然而虚拟机与宿主机之间的切换(约1000 cycles),额外的上下文切换(约8500 cycles)及跨socket时的昂贵的唤醒IPI中断,开销较大。在2.6GHz的服务器上,单次睡眠和唤醒需要若干微秒。因此物理CPU空闲和虚拟机vCPU空闲在性能方面有着显著区别。那么当业务频繁睡眠和唤醒时,问题加剧,可能造成很高的调度开销,使业务性能受损。

空闲并非它的错! —— 问题解决

Guest Idle Halt Pollling技术,使vCPU在空闲时忙等(即Polling)一段时间窗口,延迟执行HLT指令,如果在短暂的等待时间里,vCPU上业务进程被唤醒,则无需进行后续调度。该技术通过很小的边际成本,保障了业务性能。

同时该技术使用了自适应(adaptive)的算法,保障了额外成本一定产生有效收益(性能提升),使得guest idle halt polling不仅可以解决特殊场景的性能问题,也保证了通用场景不会出现性能回退(regression)。另外该技术为客户提供的可定制化的用户接口,也让客户对于折中方案有更精细化的控制。

Guest Idle Halt Poll 解决空闲的vCPU的性能问题

内核启动参数:

cpuidle_sysfs_switch     # 该配置允许运行时修改cpuidle governor
去掉idle=                # 避免idle=*屏蔽guest idle halt polling功能

使能cpuidle_sysfs_switch允许用户在运行时选择使用其它技术,例如 menu。方便客户对比不同技术的功能。

启动参数中的idle=相比于guest idle halt polling技术有更高的优先级,如果想要使用guest idle halt polling则必须保证启动参数中没有idle=的参数。

运行时参数:

echo 200000 > /sys/module/haltpoll/parameters/guest_halt_poll_ns             # 核心参数,限制polling的最长时间
echo Y > /sys/module/haltpoll/parameters/guest_halt_poll_allow_shrink        # 允许polling时间窗口缩小
echo 2 > /sys/module/haltpoll/parameters/guest_halt_poll_grow                # polling时间窗口增长系数
echo 2 > /sys/module/haltpoll/parameters/guest_halt_poll_shrink              # polling时间窗口缩小系数
echo 50000 > /sys/module/haltpoll/parameters/guest_halt_poll_grow_start      # 当guest_halt_poll_shrink为0时的时间窗口冷启动大小

guest_halt_poll_ns为guest idle halt polling技术的硬限制,建议根据业务睡眠和唤醒的频率,合理配置成间隔时长。

guest_halt_poll的allow_shrink、poll_grow、poll_shrink、grow_start四个参数用于自适应算法的调节,这些参数没有最优建议,而是对于不同的业务模型有不同的选择。我们建议客户针对业务模型探索最优的配置。

验证guest idle halt polling生效:

# cat /sys/devices/system/cpu/cpuidle/current_*
haltpoll
haltpoll

解决方案的演进史

针对这个问题的优化探索已有多年历史,解决的方案按照原理基本可以分为两类:

  1. passthrough C-State,不模拟MWAIT/HLT指令,允许虚拟机直接执行MWAIT/HLT指令,控制C-State。
  2. 在vCPU空闲后的一段时间窗口内Polling,暂不进行昂贵的切换和调度,给vCPU一个快速唤醒和恢复执行的机会。这类方案即halt polling方案

第一类方案应用场景有限,只能用于独享型虚拟机,否则物理CPU上的其它进程会starve。

第二类方案应用场景更广。最早由红帽开发的KVM Idle Halt Polling(下简称kvm haltpoll)即属于这一类方案的早期探索。Alibaba Cloud Linux 2使用的Guest Idle Halt Polling(下简称guest haltpoll)也属于这一类方案,这一方案最早由阿里云在社区提出并在内部使用,并对目前Alibaba Cloud Linux 2引入的红帽主导的guest haltpoll方案也产生了一些影响。

halt polling类型方案

kvm haltpoll在虚拟机退出到根模式后,等待一个时间窗口,在这个窗口内不触发上下文切换。一旦接收到中断信号,可以立即进入非根模式,继续执行vCPU上的业务进程。避免了部分的上下文切换因而降低了业务的唤醒延迟,但却没能避免虚拟化根模式的切换。另外kvm haltpoll还存在跨socket唤醒需要发送IPI的问题。kvm haltpoll在设计上具有无法克服的性能问题。

2.png

guest haltpoll运行在虚拟机内核中。它具有与kvm haltpoll相同的设计思想,但与kvm haltpoll不同,它不但减少多余的上下文切换,还可以直接避免多余的root mode切换,使CPU在polling阶段保持在虚拟机的非根模式中。因此更加彻底地解决了vCPU空闲虚拟化开销高的问题。另外跨socket唤醒的IPI,利用vCPU线程的polling flag,也得到优化。性能上的明显差异也是阿里云和红帽分别参与设计guest haltpoll的初衷。

3.png

两种halt polling类型方案对比

kvm haltpoll历史较长,性能比guest haltpoll较差。目前kvm haltpoll一般适用于多种不同类型虚拟机操作系统的场景,以便运行一些不支持guest haltpoll的老旧虚拟机操作系统。

而新型的guest haltpoll则在性能上有显著优势。以测试集schbench为例。guest haltpoll方案性能显著优于kvm haltpoll:

4.png

以上测试数据包含了两个benchmark,schbench和ping-pong。

schbench的测试在一台32个HT的测试虚拟机上进行,通过调节halt poll ns,使两个方案的CPU%上升相同,均为10%左右。最后对比运行结果的99.0th latency。(./schbench -c 30000 -s 30000 -m 6 -t 8 -r 30)

ping-pong的测试同样在一台32个HT的测试机上进行。该benchmark的行为是server和client两个程序相互不断发送1byte的包。通过调节halt poll ns,使两个方案的CPU%都上升到200%。最后对比测试集的运行时间。

技术揭秘

guest haltpoll基于cpuidle子系统实现。cpuidle子系统是Linux内核对硬件ACPI C-state的封装,用于空闲CPU的电源管理,它包括了三个层次:

5.png

其中cpuidle governor和cpuidle driver两个层次是模块化的。guest haltpoll也在这两个层次以模块形式实现。

guest haltpoll仅仅使用了C-state的{C0, C1}的子集,这使得guest haltpoll得以支持更多的平台和架构,让其它平台和架构也能从guest haltpoll中受益。

guest haltpoll governor中,根据vCPU的睡眠时间,设计了自适应的polling算法,保障了额外成本一定产生有效收益,使得guest haltpoll不仅可以解决特殊场景的性能问题,也保证了通用场景不会出现性能回退。

题外话

本文没有讨论独享型虚拟机,这是否意味着独享型虚拟机不能收益呢?不,使用guest idle halt polling技术,独享型虚拟机的性能同样也能略微超越原有极限。这是因为guest idle halt polling技术暴露的是一类宿主机和虚拟机上通用的问题,因此独享虚拟机也能够受益。这一问题在共享虚拟机中最为严重,因此在方案设计时也主要针对共享虚拟机。