3. Android调度器演进
Android 内核调度器的演进,本质上是为应对移动设备独特的功耗与性能平衡挑战。从桌面 Linux 的完全公平调度器(CFS)开始,到针对大小核架构的 HMP 调度器,再到引入能量感知调度(EAS),每一步都深刻影响着系统的响应速度与续航表现。本章将梳理这一演进路径,并剖析各阶段的核心机制与性能权衡。
3.1 起点:CFS 在移动端的局限
CFS(Completely Fair Scheduler)是 Linux 内核默认调度器,其核心思想是使用红黑树维护任务,保证每个任务获得公平的 CPU 时间片。然而,CFS 在设计之初主要面向服务器和桌面环境,在移动端暴露出两个关键问题:
- 功耗盲区:CFS 仅关注 CPU 时间分配的公平性,完全不考虑不同 CPU 核心的功耗差异。在大小核(big.LITTLE)架构上,它可能将后台任务调度到大核上,造成不必要的功耗浪费。
- 迁移延迟:CFS 的任务迁移决策基于负载均衡,但缺乏对核心类型(大核/小核)的感知,导致任务在大小核之间频繁迁移,增加缓存失效和迁移开销。
关键指标:在 CFS 调度下,Android 设备后台应用的平均功耗比理想值高出 15%-25%,且 UI 线程的调度延迟(sched_latency)波动较大,直接影响滑动流畅度。
3.2 HMP 调度器:异构多核的初步适配
HMP(Heterogeneous Multi-Processing)调度器是 ARM 为 big.LITTLE 架构设计的调度方案。它不再将 CPU 视为同质资源,而是引入 CPU 容量(capacity) 的概念,将大核与小核区分对待。
3.2.1 HMP 的核心机制
- CPU 容量模型:每个 CPU 核心被赋予一个容量值(通常大核为 1024,小核为 400-600),调度器根据任务负载与 CPU 容量的匹配度进行调度。
- 负载跟踪:使用 PELT(Per-Entity Load Tracking)跟踪每个任务的运行时间,计算其平均负载。
- 迁移决策:当任务负载超过小核容量阈值时,将其迁移到大核;反之则迁移回小核。
HMP 的典型配置:在 Android 内核中,HMP 通过
/sys/kernel/hmp/ 下的参数进行调优,例如 down_threshold(下迁阈值)和 up_threshold(上迁阈值),控制任务在大小核之间的迁移时机。
3.2.2 HMP 的不足
HMP 虽然解决了大小核识别问题,但其调度决策仍然基于 负载阈值,而非真正的功耗模型。这导致以下问题:
| 问题 | 表现 | 影响 |
|---|---|---|
| 阈值震荡 | 任务负载在阈值附近波动时,频繁在大小核间迁移 | 增加迁移开销,降低性能 |
| 功耗估算粗糙 | 仅通过 CPU 频率和核心类型估算功耗,未考虑电压、温度等因素 | 功耗优化不精确 |
| 缺乏全局视角 | 每个 CPU 独立决策,未考虑整个系统的功耗预算 | 多任务场景下功耗失控 |
3.2.3 HMP 调度流程 SVG
3.3 EAS 调度器:能量感知的调度革命
EAS(Energy Aware Scheduling)是继 HMP 之后的重大演进,它从 Linux 4.x 开始合入主线,并在 Android 内核中得到广泛采用。EAS 的核心思想是:在保证性能满足需求的前提下,选择能耗最低的 CPU 核心执行任务。
3.3.1 EAS 的三大支柱
| 组件 | 功能 | 关键数据 |
|---|---|---|
| CPU 容量模型 | 量化每个 CPU 核心的最大计算能力 | 通过 /sys/devices/system/cpu/cpu*/cpu_capacity 暴露 |
| 能量模型(EM) | 提供每个 CPU 在不同频率下的功耗数据 | 通过 /sys/devices/system/cpu/cpu*/energy_model 暴露 |
| 负载跟踪(PELT) | 精确跟踪每个任务的 CPU 利用率 | 以毫秒级粒度更新,反映任务真实需求 |
3.3.2 EAS 的调度决策过程
- 任务唤醒:当任务被唤醒时,EAS 遍历所有可用的 CPU 核心。
- 性能预估:根据任务的 PELT 负载,预估将其调度到每个核心上所需的 OPP(Operating Performance Point,即频率/电压组合)。
- 能耗计算:利用能量模型,计算每个候选核心在对应 OPP 下的预估功耗。
- 最优选择:选择满足性能需求且能耗最低的核心。
注意:EAS 的能耗计算依赖于平台提供的能量模型数据。如果能量模型不准确(例如未考虑漏电流或温度效应),EAS 的调度决策可能反而导致功耗增加。因此,OEM 厂商需要根据实际硬件校准能量模型。
3.3.3 EAS 调度决策 SVG
3.4 CFS、HMP、EAS 对比总结
| 特性 | CFS | HMP | EAS |
|---|---|---|---|
| 核心架构 | 同质多核 | 异构多核(大小核) | 异构多核 + 能量模型 |
| 调度依据 | 时间片公平性 | 负载阈值 | 性能 + 能耗联合优化 |
| 功耗感知 | 无 | 间接(通过核心类型) | 直接(通过能量模型) |
| 迁移决策 | 负载均衡 | 固定阈值 | 动态能耗计算 |
| Android 引入版本 | Android 早期版本 | Android 5.x - 8.x | Android 9+(主线内核 4.x+) |
| 典型功耗优化 | 无 | 10%-15% | 20%-30% |
3.5 实践建议:EAS 调优方向
在 Android 系统性能优化中,针对 EAS 的调优通常关注以下方面:
- 能量模型校准:确保
/sys/devices/system/cpu/cpu*/energy_model中的数据与实际硬件功耗曲线匹配。可以使用powercap或perf工具进行验证。 - 负载跟踪参数:调整 PELT 的半衰期(
kernel.sched_pelt_period),在响应速度和稳定性之间取得平衡。 - 调度域配置:通过
/proc/sys/kernel/sched_domain/调整调度域的层级和标志位,控制任务迁移的范围和频率。 - 关键任务标记:使用
sched_setattr()系统调用为 UI 线程设置SCHED_FLAG_UTIL_CLAMP_MIN,确保其始终获得足够的 CPU 资源。
性能分析工具:使用
schedtop、trace-cmd 和 kernel.sched_schedstats=1 可以实时观察 EAS 的调度决策,识别任务迁移和能耗异常。