系统级优化:内核调度器优化(CFS vs RT)、cpuset与cpufreq配置、ION内存分配器调优、LMK策略
各位做Camera HAL的兄弟,咱们今天聊点底层的硬核东西。系统级优化,说白了就是让内核、调度器、内存管理这些“幕后黑手”乖乖为摄像头服务。你想想看,上层算法写得再漂亮,底层调度一卡顿,预览帧率照样掉成PPT。
我个人习惯把系统级优化分成四个维度:CPU怎么跑、内存怎么分、谁先谁后、以及内存不够时杀谁。嗯,咱们一个一个来拆。
一、内核调度器:CFS vs RT,谁更适合Camera?
先问一个问题:你的Camera预览线程,到底该用CFS还是RT调度策略?
CFS(Completely Fair Scheduler)是Linux默认调度器,讲究“公平”。每个线程分点时间片,大家轮流来。但问题来了——Camera的ISP管线、HAL的buffer处理线程,它们需要的是“准时”,不是“公平”。
RT(Real-Time)调度器就不一样了。它让高优先级线程抢占CPU,直到干完活才让给别人。我在项目中遇到过,把Camera的preview线程从CFS切到RT(SCHED_FIFO),帧率抖动直接从±5ms降到±1ms以内。
核心结论:Camera关键线程(如HAL的processCaptureRequest、ISP的frame callback)建议使用RT调度。非关键线程(如metadata回调、log打印)保持CFS即可。
配置方法很简单,在init.rc或通过代码设置:
// 设置RT调度,优先级50
struct sched_param param = { .sched_priority = 50 };
sched_setscheduler(thread_id, SCHED_FIFO, ¶m);
注意:RT线程如果写死循环,整个系统会卡死。我曾经见过一个同事把RT优先级设到99,结果UI完全没响应——嗯,从那以后我规定Camera线程RT优先级最高不超过60。
二、cpuset与cpufreq:给Camera线程“包间”
cpuset是Linux内核的CPU亲和性控制机制。说白了,就是告诉内核:“Camera的线程只能跑在CPU大核上,别去小核上挤。”
我建议的配置策略:
- 大核(CPU4-7):绑定Camera HAL、ISP、算法处理线程
- 小核(CPU0-3):跑UI、网络、后台服务
- 中核(如果有):跑编解码、音视频处理
配置示例(init.rc片段):
# 创建camera专属cpuset
mkdir /dev/cpuset/camera 0770 system system
echo "4-7" > /dev/cpuset/camera/cpus
echo "0-3" > /dev/cpuset/background/cpus
# 将Camera进程移入
echo $PID > /dev/cpuset/camera/tasks
cpufreq这块,我习惯用performance governor。别跟我说省电——Camera预览时功耗本来就高,与其让频率来回跳导致帧率波动,不如直接锁高频。
小技巧:在Camera打开时动态切换governor,关闭时恢复。用sysfs写节点就行:echo "performance" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
三、ION内存分配器:别让buffer申请成为瓶颈
ION是Android的内存分配器,Camera的buffer(preview、capture、video)全走它。调优的核心就一句话:减少分配次数,增大缓存池。
我见过最典型的坑:每次预览帧都重新申请ION buffer,结果分配耗时占了帧间隔的30%。
解决方案:
- 预分配池:启动时一次性申请8-12个buffer,循环使用
- 调整heap大小:根据分辨率计算,比如1080p预览需要约6MB/帧,预留80MB给Camera
- 使用cached buffer:减少CPU与DMA之间的cache同步开销
ION配置在dts或内核cmdline中:
# 增大Camera专用heap
ion_camera_heap_size=0x5000000 # 80MB
# 启用cached分配
ion_camera_cached=1
经验数据:优化前ION分配耗时约3-5ms/次,预分配池化后降到0.1ms以内。帧率从28fps直接拉到30fps满帧。
四、LMK策略:别杀错“人”
Low Memory Killer是Android的内存回收机制。系统内存不足时,它会根据oom_score_adj值杀进程。
Camera场景下最怕什么?怕LMK把CameraService或HAL进程杀了。用户正拍照呢,突然黑屏——这体验太糟糕了。
我的调优策略:
- 降低Camera相关进程的oom_score_adj:设为-1000(不可杀)或-500(极低概率被杀)
- 提高其他后台进程的adj值:让LMK优先杀浏览器、新闻客户端
- 监控内存水位:在内存低于200MB时主动释放非关键buffer
配置示例:
# 在init.rc中设置
write /proc/$(pidof cameraserver)/oom_score_adj -500
write /proc/$(pidof mediaprovider)/oom_score_adj 900
避坑指南:我曾经把CameraService的adj设为-1000,结果系统内存耗尽时直接panic重启。后来改成-500,配合主动buffer释放,再没出过问题。
知识体系总览
下面这张图总结了系统级优化的四个维度及其关系:
这四个维度不是孤立的。你想想看,调度器决定了谁先跑,cpuset决定了跑在哪个核上,ION决定了内存够不够快,LMK决定了关键时刻谁被牺牲。它们环环相扣,任何一个短板都会让Camera体验崩盘。
嗯,系统级优化就是这样——没有银弹,只有把每个环节都做到位。我这些年踩过的坑,总结下来就一句话:给Camera最好的CPU、最快的内存、最高的优先级、最安全的保命符。
公众号:蓝海资料掘金营,微信deep3321