3、Governor详解(上):Performance Governor原理、Powersave Governor原理、Userspace Governor原理

好,咱们今天正式进入Governor的世界。说实话,很多做嵌入式或者服务器调优的朋友,对Governor的理解就停留在「省电模式」和「性能模式」这两个词上。但实际工作中,选错了Governor,轻则功耗失控,重则系统卡顿甚至宕机。我见过不止一次,有人把服务器设成Powersave,结果数据库查询延迟直接飙到秒级。

今天我们先讲三个最基础的Governor:Performance、Powersave和Userspace。它们虽然简单,但理解透了,后面讲Ondemand和Interactive时你才能举一反三。

3.1 Performance Governor:简单粗暴,但有用

Performance Governor的逻辑,说白了就一句话:CPU永远跑在最高频率。不管系统有没有负载,它都死守最高频点。

核心行为:

  • 设置CPU频率为最高可用频率(scaling_max_freq)
  • 不响应负载变化,不做任何调频决策
  • 功耗最高,延迟最低

你可能会问:「这玩意儿有啥用?不是浪费电吗?」嗯,我刚开始也这么想。直到有一次我在做实时音视频编解码的项目,发现CPU在低负载时被降频,导致编码器偶尔丢帧。换成Performance后,问题立刻消失。说白了,有些场景下,延迟比功耗更重要

看看它的内核代码实现,其实非常简单:

// drivers/cpufreq/cpufreq_performance.c
static int cpufreq_governor_performance(struct cpufreq_policy *policy,
                                        unsigned int event)
{
    switch (event) {
    case CPUFREQ_GOV_START:
    case CPUFREQ_GOV_LIMITS:
        // 直接设置到最高频率
        __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
        break;
    default:
        break;
    }
    return 0;
}

看到了吗?就两个case,一个启动,一个限制变化。没有定时器,没有负载采样,没有任何花哨的逻辑。我曾经在调试一个功耗敏感的设备时,发现Performance模式下CPU温度直接飙到85度,但响应时间稳定在1ms以内。这就是它的代价——用功耗换确定性。

我的建议:

Performance Governor适合以下场景:

  • 实时性要求高的任务(音频、视频、工业控制)
  • 短时间爆发性计算(比如编译、渲染)
  • 服务器端对延迟敏感的服务(比如高频交易)

但注意,别在笔记本或手机上长期开它,电池会哭的。

3.2 Powersave Governor:省电的极端

和Performance相反,Powersave Governor让CPU永远跑在最低频率。它的逻辑同样简单:

核心行为:

  • 设置CPU频率为最低可用频率(scaling_min_freq)
  • 同样不响应负载变化
  • 功耗最低,延迟最高

你想想看,如果系统一直跑在最低频,那省电效果肯定好。但代价是什么?我举个例子:有一次我在调试一个IoT网关设备,默认用了Powersave Governor。结果设备在收到网络数据包时,CPU需要花几十毫秒才能从低频率「爬」上来处理中断。嗯,网络丢包率直接爆表。

它的代码实现和Performance几乎对称:

// drivers/cpufreq/cpufreq_powersave.c
static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
                                      unsigned int event)
{
    switch (event) {
    case CPUFREQ_GOV_START:
    case CPUFREQ_GOV_LIMITS:
        // 直接设置到最低频率
        __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
        break;
    default:
        break;
    }
    return 0;
}

注意看,它用的是CPUFREQ_RELATION_L,表示选择小于等于目标频率的最低可用频率。而Performance用的是CPUFREQ_RELATION_H,选择大于等于目标频率的最高可用频率。这两个宏的区别,我建议你记住,后面调优时会用到。

避坑指南:

我曾经在一个嵌入式项目里,把Powersave设为默认Governor,结果系统在启动阶段加载驱动时,因为频率太低导致I/O超时。后来我加了一个启动阶段的频率提升策略才解决。所以,不要在需要快速响应的场景下用Powersave,尤其是中断密集型的任务。

3.3 Userspace Governor:把控制权交给你

Userspace Governor就更有意思了。它不自己做调频决策,而是把频率设置接口暴露给用户空间。说白了,你想让CPU跑多快,你自己说了算

它的工作原理是这样的:

  • 内核提供一个sysfs接口:/sys/devices/system/cpu/cpuX/cpufreq/scaling_setspeed
  • 用户空间程序(比如脚本、守护进程)通过写这个文件来设置频率
  • 内核不做任何干预,完全听你的

我个人的习惯是,在调试阶段或者做定制化功耗管理时,会临时切换到Userspace Governor。比如我想测试某个频率下的性能表现,直接写一个值进去就行:

# 切换到Userspace Governor
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

# 设置频率为1.2GHz
echo 1200000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed

它的内核实现也很直白:

// drivers/cpufreq/cpufreq_userspace.c
static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
{
    int ret;
    
    if (!policy->governor_enabled)
        return -EINVAL;
    
    // 直接调用驱动层的target接口
    ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
    
    if (!ret)
        policy->cur = freq;
    
    return ret;
}

注意这里有个细节:policy->governor_enabled这个标志位。如果Governor还没启动,你写setspeed会返回错误。我曾经踩过这个坑,在系统初始化阶段过早写频率,结果一直报错,排查了半天才发现是Governor还没加载完。

实用技巧:

Userspace Governor最适合做两件事:

  1. 性能测试:固定频率跑benchmark,排除调频干扰
  2. 定制化调频策略:比如根据温度、电池电量、用户行为等自定义调频逻辑

但注意,如果你没有写用户空间程序,千万别长期用Userspace。否则CPU会一直卡在你上次设置的频率上,不会自动调整。

3.4 三个Governor的对比总结

好了,三个Governor讲完了。我整理了一个表格,方便你对比:

特性 Performance Powersave Userspace
频率策略 固定最高频 固定最低频 用户自定义
负载响应 不响应 不响应 不响应(需用户程序控制)
功耗表现 最高 最低 取决于用户设置
延迟表现 最低 最高 取决于用户设置
适用场景 实时、低延迟 后台、空闲任务 调试、定制化
内核代码量 约30行 约30行 约100行

看到没?Performance和Powersave就是两个极端,代码量都很少。Userspace稍微复杂一点,因为它要处理用户空间的请求。但整体来说,这三个Governor都属于「静态调频」的范畴——它们不会根据负载动态调整频率。

下一节我们会讲Ondemand和Conservative这两个动态调频Governor,那才是真正考验调优功底的地方。嗯,今天就先到这里,你先把这三个基础Governor吃透,后面才能跟上节奏。

一句话总结:

Performance保延迟,Powersave保功耗,Userspace保自由。选哪个,看你的业务优先级。