选对调度器,让你的设备“纵享丝滑”
随着移动设备的普及,用户对设备的操作体验有了越来越高的要求。能够实现一些硬性操作已经是最基本的条件了,是否可以提供更流畅的操作体验、更让人舒适的交互方式等,逐渐变成了设备之间“攀比”的方式,想要满足这些需求,首先需要明确一个合适、高效的 CPU 调度,再去优化能耗。
为了保证系统的性能和响应时间,在不同的场景下,如何实现多任务的并发执行、怎样选择不同的调度算法和策略呢?
01 ESA 调度器缘起
Linux 内核一直使用完全公平调度器 CFS ( Completely Fair Scheduler )作为默认调度器,其使用的 PELT ( per entity load tracking )跟踪任务负载,更适合 CPU 高吞吐量场景,而对于现在流行的手机或者消费电子等对功耗敏感的设备,则存在明显的局限性,比如:
CFS 主要是为了服务器性能优先场景而设计的,主要目标是最大限度地提高系统的吞吐量,CFS 调度的目标是所有任务都平均分配到系统所有可用的 CPU 上。
CFS 主要针对 SMP 系统,对于非 SMP 系统支持不足,比如说 arm.big.little 架构以及 intel PE 核架构。
没有充分利用各个核的功耗、性能、频率差异来达到性能和功耗的最优平衡。
EAS 由来
那如何解决 CFS 调度器的局限性问题呢?
ARM 和 Linaro 改变了 CFS 的调度策略、调度器、CPUidle 和 CPUFreq 模块的相对独立的情况,让它们可以在一起紧密地工作,从而进一步优化功耗和效率,后来我们把这个改变叫作 Energy Aware Scheduling ,简称 EAS 。
EAS 的能力
EAS 调度器的设计目标是在保证系统性能的前提下尽可能地降低功能。
Linux 内核主要分为三个核心部分:Linux 调度程序( CFS )、Linux cpuidle 、Linux cpufreq。
它们相互独立,并有其独特的核心功能:
CFS 可以统一这 3 个模块的各个部分,并将它们一起计算来使它们尽可能高效;
CPUIdle 尝试决定 CPU 何时进入空闲模式;
CPUFreq 决定何时加速或降低 CPU。
而 EAS 引入了使用能量模型来将以上三个独立的部分统一,最大效率地节省功耗提高性能。
不仅如此,EAS 还将进程/程序/应用分为四个 cgroup,即 top-app, system-background, foreground, and background,将要处理的任务放入其中一个类别中,然后为该类别提供 CPU power ,并将工作委派给不同的 CPU 核心。
Top-app 是完成的最高优先级,其次是 forground, background 和 system-background gorup。Backgound group 与 system-background group 具有相同的优先级,但 system-background group 通常也可以访问更多的核心。
实际上, EAS 正在将 Linux 内核的核心部分整合到一个进程中。
02 EAS 如何运作
当我们唤醒设备时, EAS 将选择处于最浅空闲状态的核心,从而最大限度地减少唤醒设备所需的能量;如果不需要,它不会唤醒 big cluster ,这有助于降低使用设备所需的功率。
为了实现这一动作,我们必须设置用来表现 CPU 当前的 loading 情况的负载跟踪。文章开头我们提到了 PELT 的负载跟踪算法无法调节 CPU 运行功率,换言之,不论 CPU 负载的高低, PELT 始终保持着 100% 持续运行,这在很大程度上拖延降低 CPU 频率的速度,从而增加 CPU 功耗。
那将降低设备所需功率作为主旨的 EAS 要使用哪种负载跟踪算法呢?
EAS 为何选择 WALT 算法?
WALT ( Windows-Assist Load Tracing ) 将一小段时间内的 CPU loading 情况计算出对应的结果,作为一个 window ;然后再统计多个类似的 window 。将它们进行计算后即可得到 task demand 结果,并将其运用于 CPU 频率调节和负载均衡。
因此,在与用户交互时它可以尽快响应,并及时反应负载的增加和减少以驱动频点及时变化,对于突变性质的负载反应友好,不论是负载的上升或者下降,都可以及时进行调节,也经常用于移动设备对性能功耗要求比较高的场景
WALT 如何处理
那 WALT 到底能实现什么效果呢?
保持对于所有 Task-entity 的跟踪 ;
在此前 usage(load)的基础上,添加对于 demand 的记录,用于之后预测;
每个 CPU 上 runqueue 的整体负载仍为所有 Task 统计的 sum;
当然,除了以上这些功能之外,WALT 能实现这些效果还是依托于其独特的核心结构体和计算差异:
mark_start 代表了任务的当前采样点起始时间;
demand 是预测的 task demand ;
sum_history [] 是任务在最近 5 个窗口中分别运行的时间。
通过以上的计算,WALT 就可以清晰得知每个 window 的功率,从而了解各个核的功耗、性能、频率差异来达到性能和功耗的最优平衡。
03“横向出发”搭建数据体系
但是 WALT 也不是十全十美的。
使用 WALT 时我们可以发现,在当前任务监测工具 top、ps 都只能看到任务的 cpu 占用率,而小核的 100% CPU 占用率和大核的 100% CPU 占用率完全不是一个量级,因此我们并无法得知当前 CPU 在多少频率下的占用率!
但无论是为了更好的系统性能优化、故障排除还是为了更优的资源管理和系统监控,都离不开对 CPU 的实际频率和占用率的分析。尤其在数字化大力发展的今天,互联网行业“硝烟四起”,抛开技术不谈,拥有更准确的信息和数据,就代表着可以快人一步、给用户带来更流畅的操作感。
而鼎道专注于开发“以人为本”的操作系统的历程中,我们将为用户提供更便捷、安全、绿色的操作体验作为一个目标,因此,我们直面了 WALT 现有的局限性,并想方设法将其优化,开发了归一化负载查询功能,可以为开发者提供更清晰的 CPU 占用率数据!这里也为大家埋一个伏笔,之后我们会单独开辟一个专题,来和大家共同探讨此类问题!也欢迎大家加入鼎道生态,发表你的想法或见解~
评论