3、CPUFreq Governor深度解析:performance、powersave、userspace、ondemand、conservative、schedutil

各位好,我是老李。今天我们来啃一块硬骨头——CPUFreq Governor。说白了,它就是Linux内核里控制CPU频率和电压的调度策略。你手机、服务器、嵌入式设备里,CPU频率怎么变,全看它脸色。

我个人习惯把Governor比作「司机」。有的司机一脚油门踩到底,有的司机慢慢悠悠省油,还有的司机看路况实时调整。嗯,今天我们就把这几个司机挨个拉出来遛遛。

3.1 performance Governor:简单粗暴

这个Governor的逻辑就一句话:CPU频率直接拉到最高,绝不降频

我在项目中遇到过,有些实时性要求极高的场景,比如工业控制、音频处理,用performance最省心。为什么?因为频率不变,延迟就稳定。你想想看,如果CPU突然降频,音频缓冲区可能就欠载了,那声音就「咔咔」断断续续。

适用场景: 追求极致性能,不在乎功耗。比如跑分、游戏、实时计算。
注意: 别在笔记本或手机上长期开performance。我曾经见过一个同事,笔记本一直开performance模式,结果电池鼓包了。嗯,这不是玩笑。

3.2 powersave Governor:省电狂魔

和performance正好相反,powersave把频率锁在最低档。说白了,就是「能省则省,能慢则慢」。

这个Governor适合什么场景?后台下载、待机、或者你只是打开个文本编辑器。我建议,如果你在做IoT设备或者电池供电的嵌入式产品,powersave可以作为默认策略。但要注意,如果突然有高负载任务,系统会卡到你怀疑人生。

小技巧: 我习惯在系统空闲时动态切换到powersave,负载上来再切回ondemand。后面会讲怎么自动切换。

3.3 userspace Governor:手动挡

这个Governor把频率控制权完全交给用户空间。内核不干预,你通过/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed这个文件手动写频率值。

说实话,现在很少有人直接用userspace了。为什么?因为手动调频太麻烦,而且你很难预测负载变化。不过,我在调试新硬件时偶尔会用——比如验证某个频率点是否稳定,或者测试DVFS的边界条件。

# 手动设置CPU0频率为1.2GHz
echo 1200000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
避坑指南: 我曾经在某个ARM平台上,直接写了一个不支持的频率值,结果系统直接死机。所以写之前,先看看scaling_available_frequencies文件里有哪些合法值。

3.4 ondemand Governor:经典老将

ondemand是Linux内核里最经典的动态调频策略。它的核心逻辑是:负载高了就升频,负载低了就降频。怎么判断负载?看CPU的「忙闲比」——也就是idle时间占比。

具体来说,内核会定期采样(比如每10ms),如果CPU忙的时间超过某个阈值(默认95%),就立刻跳到最高频。如果负载降下来,再慢慢降频。

我在项目中遇到过,ondemand在服务器上表现不错,但在移动设备上有个问题:响应不够快。比如你突然点了一下屏幕,CPU可能还在低频,等它反应过来,用户已经觉得卡了。

关键参数:
  • up_threshold:升频阈值,默认95%。调低这个值可以让CPU更积极升频。
  • sampling_rate:采样周期,单位微秒。调小可以加快响应,但会增加开销。

3.5 conservative Governor:温和派

conservative和ondemand很像,但它的调频策略更「温柔」。ondemand是一步到位跳到最高频,而conservative是逐步升频,每次只跳一档。

你想想看,这样有什么好处?功耗波动小,更平滑。比如你只是偶尔有个小负载,conservative不会一下子把频率拉满,而是慢慢试探。这样电池寿命会更好。

但缺点也很明显:响应慢。如果突然来个大任务,conservative要好几步才能升到最高频,这段时间系统性能会受影响。我个人习惯,在功耗敏感但负载变化不剧烈的场景用conservative,比如电子书阅读器。

参数调整:
  • freq_step:每次升频的步长,默认5%。调大可以加快升频速度。
  • down_threshold:降频阈值,默认20%。低于这个值就开始降频。

3.6 schedutil Governor:现代新秀

schedutil是Linux 4.7之后引入的,也是目前最推荐的Governor。它和前面几个最大的区别是:不再依赖独立的采样线程,而是直接利用调度器的负载信息

说白了,调度器(CFS)本身就知道每个CPU上跑了多少任务、每个任务需要多少算力。schedutil直接从调度器拿这些数据,然后计算目标频率。这样做的好处是:响应更快,更精准

我在项目中测试过,schedutil在手机上的表现明显优于ondemand。比如你滑动屏幕,schedutil几乎能瞬间把频率提上去,而ondemand会有几十毫秒的延迟。

# 查看当前使用的governor
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

# 切换到schedutil
echo schedutil > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
schedutil的优势:
  • 基于调度器负载,响应延迟低(微秒级)
  • 支持EAS(Energy-Aware Scheduling),能同时考虑性能和功耗
  • 不需要额外的采样线程,节省CPU开销
注意: schedutil需要内核开启CONFIG_CPU_FREQ_GOV_SCHEDUTIL。而且它依赖调度器的负载跟踪,如果调度器本身有问题,schedutil也会受影响。我曾经在某个老内核上遇到过schedutil导致频率震荡的问题,后来发现是调度器的PELT算法参数没调好。

3.7 如何选择?一张表说清楚

Governor 特点 适用场景 功耗 性能
performance 固定最高频 实时、跑分、游戏 最高 最高
powersave 固定最低频 待机、后台下载 最低 最低
userspace 用户手动控制 调试、测试 取决于设置 取决于设置
ondemand 负载高升频,采样周期调频 服务器、桌面 中等
conservative 逐步升频,平滑过渡 功耗敏感、负载平稳 较低 中等
schedutil 基于调度器负载,响应快 移动设备、现代Linux

最后说一句,没有「最好」的Governor,只有「最合适」的。我建议你在实际项目中,先默认用schedutil,如果遇到问题再换ondemand或conservative。至于performance和powersave,除非你有特殊需求,否则别碰。

嗯,这一章就到这里。下一章我们聊聊怎么动态切换Governor,以及如何调优参数。到时候我会分享一些我在手机和服务器上的实战经验。