16、性能调优:CPU 调频、LMK 与 OOM、Traceview 与 Perfetto 分析

性能调优,说白了就是让系统跑得更快、更稳、更省电。我做了这么多年嵌入式Android,最深的体会是:性能问题往往不是单一原因造成的,而是CPU、内存、I/O等多个子系统互相拉扯的结果。今天我们就从三个核心维度入手,把这块硬骨头啃下来。

16.1 CPU 调频:别让大核闲着,也别让小核累死

CPU调频,就是动态调整CPU的运行频率和核心数量。Android系统默认的调频策略,说白了是个“和事佬”——它尽量平衡性能和功耗。但实际项目中,这种平衡往往不够用。

调频策略有哪些?

  • performance:最高频率一直跑,性能拉满,但电池会哭。
  • powersave:最低频率,省电第一,适合后台任务。
  • ondemand:按需调频,负载高了就升频,低了就降频。这是老内核的默认策略。
  • interactive:比ondemand更激进,响应更快。曾经是Android的标配。
  • schedutil:基于调度器的调频,能更精准地感知任务需求。现在的主流选择。

核心观点:我个人习惯在游戏或视频类产品中,把前台应用绑定到大核,并锁定schedutil策略。后台服务则丢给小核,用powersave。这样既保证了流畅度,又不会让整机功耗爆炸。

怎么调? 直接写节点就行:

# 查看当前策略
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

# 设置策略
echo "schedutil" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

# 绑定进程到特定核心(以CPU0-3小核为例)
taskset -p 0x0f <PID>

避坑指南:我曾经在某个项目里,直接给所有核心都设成performance,结果跑分是高了,但手机发烫到能煎鸡蛋。后来改成动态绑核+按需调频,才把温度压下来。记住:调频不是越猛越好,而是“够用就好”。

16.2 LMK 与 OOM:内存不够时,谁该“牺牲”?

Android的内存管理,核心就是Low Memory Killer(LMK)和Out-Of-Memory(OOM)机制。它们俩的关系,你可以这么理解:LMK是“预警机制”,OOM是“最后手段”。

LMK的工作原理:系统给每个进程分配一个“oom_score_adj”值,值越高,越容易被杀。当内存低于某个阈值时,LMK会从高到低依次杀掉进程。

关键阈值

内存级别 触发条件 杀掉目标
警戒级 可用内存 < 150MB 后台缓存进程(oom_score_adj >= 900)
严重级 可用内存 < 100MB 空进程、服务进程(oom_score_adj >= 700)
临界级 可用内存 < 50MB 可见进程、前台进程(oom_score_adj >= 0)

怎么调优? 我建议你重点关注两个方向:

  • 调整阈值:在init.rc或内核dts中修改LMK参数。比如把警戒级阈值调高,让系统更早开始杀进程,避免突然卡顿。
  • 保护关键进程:把系统服务、前台应用的oom_score_adj设低一点(比如-100),让它们不容易被误杀。

注意:OOM killer一旦触发,系统会直接崩溃或重启。所以我们的目标应该是:让LMK在OOM之前就把问题解决掉。我曾经见过一个项目,因为LMK阈值设得太低,导致系统频繁OOM重启。后来把阈值调高了一倍,问题就消失了。

16.3 Traceview 与 Perfetto:性能分析的“火眼金睛”

工具用得好,下班下得早。Traceview和Perfetto,就是Android性能分析的两把利器。

Traceview:老牌工具,适合分析单个应用的CPU耗时。它会记录每个方法的调用次数和执行时间。用法很简单:

// 在代码中打点
Debug.startMethodTracing("app_trace");
// ... 你的业务逻辑 ...
Debug.stopMethodTracing();

// 生成的 .trace 文件用 Android Studio 的 Profiler 打开

Perfetto:新一代神器,能分析整个系统的性能,包括CPU、内存、I/O、调度等。我强烈建议你学会用它。

Perfetto的基本用法

# 抓取一次trace(持续10秒)
adb shell perfetto -o /data/misc/perfetto-traces/trace.perfetto-trace \
  -t 10s \
  sched freq idle am wm gfx view

# 拉取到电脑
adb pull /data/misc/perfetto-traces/trace.perfetto-trace

# 打开 https://ui.perfetto.dev 加载文件

个人经验:我遇到过一个棘手问题——系统偶尔卡顿,但抓不到规律。后来用Perfetto连续抓了30分钟的trace,终于发现是某个内核驱动在特定条件下触发了高优先级中断,占用了大量CPU时间。这种问题,用Traceview根本看不出来,因为它是应用层的工具。

Perfetto的核心分析思路

  • 看CPU调度:检查是否有核心过载,或者任务频繁迁移。
  • 看唤醒链:一个任务被谁唤醒?是不是有锁竞争?
  • 看内存压力:是否有频繁的page reclaim或kswapd活动。
  • 看I/O:是否有大量的磁盘读写导致阻塞。

小技巧:Perfetto的SQL查询功能非常强大。比如你想找出所有耗时超过100ms的binder调用,直接写SQL查就行。我个人习惯把常用的查询存成模板,遇到问题直接套用,效率很高。

16.4 知识体系总览

下面这张图,帮你把本章的核心逻辑串起来:

性能调优核心逻辑 CPU调频 策略选择 + 绑核 LMK / OOM 阈值调整 + 进程保护 Trace / Perfetto 抓取 + 分析 + SQL 性能问题定位与解决 流畅度提升 减少卡顿、掉帧 功耗降低 延长续航、控制发热 稳定性增强 减少ANR、OOM重启 三者联动:调频保证CPU响应,LMK控制内存水位,Trace验证效果

这张图想表达的是:CPU调频、LMK/OOM、Trace分析,三者不是孤立的。调频调得好,内存压力就小;LMK杀得准,CPU就不用频繁处理OOM;而Trace工具,就是验证这一切是否有效的“裁判”。

嗯,性能调优没有银弹。但只要你掌握了这三个维度的核心方法,再遇到卡顿、发热、重启等问题,就不会慌了。记住:先定位,再动手,最后验证。这是我一直坚持的原则。

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