21、系统级延时优化:关闭SELinux/权限影响、调整kernel.sched_latency_ns、禁用不必要的后台服务
系统级优化,说白了就是给音频铺一条高速公路。你想想看,音频数据从APP到扬声器,中间要经过多少层?每一层都可能成为瓶颈。今天聊的三个优化点,是我在多个项目中反复验证过的「三板斧」。
21.1 关闭SELinux:是福是祸?
SELinux是个好东西,它保证了系统安全。但做音频低延时的时候,它经常添乱。我遇到过最夸张的一次,SELinux策略导致音频线程被挂起长达50ms——这在低延时场景下简直是灾难。
临时关闭的方法很简单:
# 查看当前状态
getenforce
# 临时关闭(重启后失效)
setenforce 0
# 永久关闭(不推荐)
# 修改 /etc/selinux/config 文件
# SELINUX=disabled
我个人习惯的做法是:调试阶段用 setenforce 0,确认问题后,再去编写针对性的SELinux策略。这样既保证了安全,又不影响性能。
21.2 调整kernel.sched_latency_ns
这个参数控制着调度器的延迟目标。默认值通常是24ms,对音频来说太大了。你想想看,一个音频buffer可能只有5ms,调度器却允许24ms的延迟——这怎么行?
我建议的调整方案:
# 查看当前值
cat /proc/sys/kernel/sched_latency_ns
# 临时调整(单位:纳秒)
echo 3000000 > /proc/sys/kernel/sched_latency_ns
# 永久生效
# 在 /etc/sysctl.conf 中添加
kernel.sched_latency_ns=3000000
我在项目中遇到过一个问题:把sched_latency_ns调得太低,结果UI线程卡顿了。原因是调度器过于激进地切换任务,导致UI渲染被频繁打断。后来我找到了平衡点——3ms,音频和UI都能正常工作。
21.3 禁用不必要的后台服务
后台服务越多,CPU争抢越激烈。音频线程需要的是「独占」式的CPU时间,而不是跟一堆服务抢资源。
常见的「捣乱分子」:
| 服务名称 | 影响 | 处理方式 |
|---|---|---|
| com.google.android.gms | 频繁唤醒CPU | 限制后台活动 |
| com.android.systemui | 动画渲染抢CPU | 降低动画帧率 |
| com.android.phone | 信号扫描干扰 | 飞行模式测试 |
| com.android.bluetooth | 蓝牙扫描 | 关闭蓝牙 |
禁用服务的命令:
# 查看运行中的服务
adb shell dumpsys activity services | grep "ServiceRecord"
# 停用特定服务(需要root)
pm disable com.example.service
# 或者用kill命令(临时)
kill -9 [PID]
核心思路: 音频测试时,尽量保持系统「干净」。我一般会准备一个专门的测试ROM,只保留核心服务。这样测出来的延时数据才是真实的。
21.4 知识体系总览
下面这张图,把三个优化点的关系梳理清楚了:
21.5 实战中的坑
我曾经在一个项目中,把SELinux关了,sched_latency_ns也调了,后台服务也禁了——但延时还是高。排查了半天,发现是某个系统服务在后台偷偷重启了。嗯,这里要注意:有些服务是「打不死的小强」,禁用后会自动重启。
解决办法是:用 pm disable 配合 pm hide,双重保险。
# 先禁用
pm disable com.example.stubborn.service
# 再隐藏(防止自动重启)
pm hide com.example.stubborn.service
top -d 1 实时监控CPU占用。如果发现某个进程频繁出现,那它就是潜在的干扰源。
还有一个坑:调整sched_latency_ns后,记得重启音频服务。否则调度器可能还在用旧参数。我习惯的做法是:
# 调整参数
echo 3000000 > /proc/sys/kernel/sched_latency_ns
# 重启音频服务
killall audioserver
# 或者
stop audioserver && start audioserver
说白了,系统级优化就是「做减法」。去掉不必要的干扰,让音频线程跑得更顺畅。这三个点,你可以在自己的设备上试试看。效果立竿见影。