3. CPU性能调优:CPU频率与调度策略、大小核架构优化、负载均衡

好,咱们进入第三章。这一章聊的是CPU调优,说白了就是让芯片的“大脑”跑得更聪明。不是一味地跑得快,而是该快的时候快,该省电的时候省电。我在联发科调过不少项目,这块坑不少,咱们一个一个说。

3.1 CPU频率与调度策略:别让CPU傻跑

CPU频率控制,是性能调优最直接的手段。但很多人一上来就“拉满频率”,这其实是个误区。你想想看,一个App只是滑动列表,你让大核跑2.8GHz,除了发热和耗电,用户体验并不会有提升。

我个人习惯,先看场景。联发科的平台里,CPU调频主要通过 cpufreq 框架。核心是这几个governor:

Governor 特点 适用场景
performance 一直最高频,性能最强 跑分、游戏加载
powersave 一直最低频,最省电 待机、后台任务
ondemand 负载上来才升频,有延迟 老平台兼容
interactive 根据负载预测调频,响应快 日常滑动、轻交互
schedutil 基于调度器负载,更精准 大小核架构首选

我在项目中遇到过,某款手机刷微博时发热严重。查了一圈,发现用的是 performance governor。改成 schedutil 后,温度降了5度,流畅度几乎没变。嗯,这里要注意,schedutil 需要内核支持,联发科新平台基本都默认开了。

核心原则:频率跟着负载走,别让CPU“空转高频”。

3.2 大小核架构优化:把活分给对的人

联发科的大小核架构,比如天玑系列的“1+3+4”或“4+4”,不是摆设。大核(Cortex-X系列)负责爆发力,中核(A78/A710)负责日常主力,小核(A55/A510)负责省电。

但很多开发者没用好。我曾经见过一个App,后台轮询任务跑在了大核上,白白耗电。正确的做法是什么?

  • 前台交互任务:丢给中核或大核,保证响应快。
  • 后台定时任务:绑定到小核,省电第一。
  • 游戏渲染线程:锁定到大核,避免调度抖动。

在联发科平台上,可以用 tasksetsched_setaffinity 来绑定CPU。举个例子:

// 将当前线程绑定到CPU2-3(中核)
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(2, &mask);
CPU_SET(3, &mask);
sched_setaffinity(0, sizeof(mask), &mask);

小技巧:联发科的 cpu_capacity 节点可以查看每个核的算力权重。比如大核是1024,小核是400。调度器会根据这个权重分配任务。

另外,大小核切换有个“迁移延迟”。任务从小核搬到大核,需要时间。我建议,如果任务周期短(比如几十毫秒),就别来回迁移了,固定在一个核上反而更高效。

3.3 负载均衡:别让一个核累死,其他核看戏

负载均衡,说白了就是让所有CPU核“雨露均沾”。但联发科的调度器(EAS,Energy Aware Scheduling)不是简单平均分配,而是考虑功耗的。

EAS的核心思想:在满足性能的前提下,尽量用能效比高的核。比如,一个轻任务,小核能搞定,就别往大核上放。

我在项目中遇到过一个问题:手机充电时,某个核温度特别高,其他核却闲着。查了 /proc/stat/sys/devices/system/cpu/cpu*/cpufreq/stats,发现是某个驱动线程绑死了CPU0,导致它一直高频运行。

解决办法:

  • 检查是否有线程绑核不合理,用 ps -eLo pid,tid,comm,psr 查看。
  • 调整调度器参数,比如 /sys/kernel/debug/sched_features 里的 ENERGY_AWARE 开关。
  • 如果某个核过热,可以暂时把它从调度池中移除:echo 0 > /sys/devices/system/cpu/cpu4/online

警告:不要随意关核!关核后,剩余核的负载会飙升,反而更耗电。只有在散热实在压不住时,才作为临时手段。

最后,分享一个我常用的调优流程:

  1. 先用 perf top 看哪个函数吃CPU最多。
  2. 再用 trace-cmd 抓调度事件,看任务在核间怎么跑的。
  3. 最后根据数据,调整绑核或governor参数。

嗯,这一章就到这里。记住,CPU调优不是“大力出奇迹”,而是“精准匹配”。下一章咱们聊内存,那又是另一片天地了。

本章小结:

  • 频率用 schedutil,别用 performance 硬怼。
  • 大小核要“人尽其才”,后台任务绑小核。
  • 负载均衡靠EAS,别手动瞎干预。

公众号:蓝海资料掘金营,微信deep3321