系统级优化:内核调度器优化(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释放,再没出过问题。

知识体系总览

下面这张图总结了系统级优化的四个维度及其关系:

Camera系统级优化四维模型 1. 内核调度器 • CFS:公平调度,适合非关键线程 • RT:实时抢占,Camera关键线程必选 • 优先级建议:50-60,避免系统卡死 → 目标:帧率抖动 < 1ms 2. cpuset & cpufreq • 大核绑定:Camera HAL + ISP线程 • 小核隔离:UI、后台服务 • cpufreq:performance governor锁频 → 目标:CPU资源独占,无竞争 3. ION内存分配器 • 预分配池:8-12个buffer循环使用 • heap大小:根据分辨率计算 • cached buffer:减少cache同步 → 目标:分配耗时 < 0.1ms 4. LMK策略 • Camera进程adj:-500(不可杀) • 后台进程adj:900(优先杀) • 内存水位监控:主动释放buffer → 目标:Camera永不被杀 四维联动,缺一不可。任何一个短板都会导致Camera性能瓶颈。

这四个维度不是孤立的。你想想看,调度器决定了谁先跑,cpuset决定了跑在哪个核上,ION决定了内存够不够快,LMK决定了关键时刻谁被牺牲。它们环环相扣,任何一个短板都会让Camera体验崩盘。

嗯,系统级优化就是这样——没有银弹,只有把每个环节都做到位。我这些年踩过的坑,总结下来就一句话:给Camera最好的CPU、最快的内存、最高的优先级、最安全的保命符


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