49

省钱,效率不打折!—— Guest Idle Halt Polling 技术揭秘

 3 years ago
source link: https://kernel.taobao.org/2020/07/Guest-Idle-Halt-Polling/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Jul 9, 2020

省钱,效率不打折!—— Guest Idle Halt Polling 技术揭秘

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技术暴露的是一类宿主机和虚拟机上通用的问题,因此独享虚拟机也能够受益。这一问题在共享虚拟机中最为严重,因此在方案设计时也主要针对共享虚拟机。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK