目录
背景
一、性能优化关键点众览
二、性能关键技术
1. CPU调度
1.1 调度单位
1.2 线程状态
1.3 线程优先级
1.4 CPU调度策略
1.4.1 调度器
1.4.2 CPUFreq Governor
1.4.3 CGroup
1.5 PerfLock
1.6 进程冻结
1.7 LMKD
1.7.1 水线
1.7.2 ADJ
1.8 温控
1.8.1 温控配置和策略
2. IO调度
3. 内存分配
3.1 内存分配器
3.2 内存压缩和回收
3.3 Camera内存
4. 锁机制
5. IPC
6. Graphics Framework
7. HW Performance
三、性能分析工具
1. Perfetto/Systrace/Atrace
2. Simpleperf & 火焰图
3. Android Profiler
4. ftrace
5. Linux perf工具
6. eBPF
四、Camera场景性能分析
1.启动
1.1 冷启动
1.1.1 关键路径
1.1.2 流程分析
1.1.3 关键点
1.2 热启动
1.2 预览卡顿
2. 模式切换
3. Lens切换
4. 拍照
5. 录像
五、优化点
1. 异步化
2. 提前和延后
3. IO
4. 调度优化
5. 业务逻辑优化
小结
做camera性能优化方面的工作有几年了,想写一篇文章简单介绍一下其中涉及到的具体技术,这篇文章会大概介绍一下涉及到的技术。
性能优化分析方向:给了多少资源和做了多少事。
线程是Linux的最小调度单位,而资源是以进程为单位进行分配和管理,包括程序(program text)、数据(data )、文件(open file)等,这些资源由同一进程下的线程共享。
分析性能问题时,主要关注下面几种状态:
Linux线程优先级
Linux线程优先级的范围是 0 ~ 139,值越小,优先级越高。userspace线程优先级的范围是 100 ~ 139,默认创建的线程优先级是120,对应的nice值是0,nice值的范围是 -20 ~ 19,对应的优先级是 100 ~ 139。只有内核线程才支持低于100的优先级,优先级低于100的线程称为RT级线程。
前面值的定义可以从如下链接 https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/include/linux/sched/prio.h?q=linux%2Fsched%2Fprio.h 获取。
Android的Process类封装了线程优先级设置接口,范围是 -20 ~ 19,跟Linux的nice值一致。Android预定义了一些优先级给系统使用。代码详细见如下:
https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:frameworks/base/core/java/android/os/Process.java?q=java%2Fandroid%2Fos%2FProcess.java
线程优先级 | nice值 | 解释 |
THREAD_PRIORITY_LOWEST | 19 | 最低优先级 |
THREAD_PRIORITY_BACKGROUND | 10 | 后台 |
THREAD_PRIORITY_LESS_FAVORABLE | 1 | 比默认略低 |
THREAD_PRIORITY_DEFAULT | 0 | 默认 |
THREAD_PRIORITY_MORE_FAVORABLE | -1 | 比默认略高 |
THREAD_PRIORITY_FOREGROUND | -2 | 前台 |
THREAD_PRIORITY_DISPLAY | -4 | 显示相关 |
THREAD_PRIORITY_URGENT_DISPLAY | -8 | 显示(更为重要),input事件 |
THREAD_PRIORITY_AUDIO | -16 | 音频相关 |
THREAD_PRIORITY_URGENT_AUDIO | -19 | 音频(更为重要) |
Java线程优先级
Java标准接口是通过Thread类设置优先级,范围为1 ~ 10。代码详细见如下所示:
https://cs.android.com/android/platform/superproject/main/+/main:libcore/openjdk_java_files.bp;l=250?q=main%2Fjava%2Fjava%2Flang%2FThread.java
Java优先级最终也要通过系统调用来设置进程的NICE值来调整进程的优先级的。代码如下所示:
https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:art/runtime/thread.cc?q=art%2Fruntime%2Fthread.cc
static const int kNiceValues[art::palette::kNumManagedThreadPriorities] = {
ANDROID_PRIORITY_LOWEST, // 1 (MIN_PRIORITY)
ANDROID_PRIORITY_BACKGROUND + 6,
ANDROID_PRIORITY_BACKGROUND + 3,
ANDROID_PRIORITY_BACKGROUND,
ANDROID_PRIORITY_NORMAL, // 5 (NORM_PRIORITY)
ANDROID_PRIORITY_NORMAL - 2,
ANDROID_PRIORITY_NORMAL - 4,
ANDROID_PRIORITY_URGENT_DISPLAY + 3,
ANDROID_PRIORITY_URGENT_DISPLAY + 2,
ANDROID_PRIORITY_URGENT_DISPLAY // 10 (MAX_PRIORITY)
};
palette_status_t PaletteSchedSetPriority(int32_t tid, int32_t managed_priority) {
if (managed_priority < art::palette::kMinManagedThreadPriority ||
managed_priority > art::palette::kMaxManagedThreadPriority) {
return PALETTE_STATUS_INVALID_ARGUMENT;
}
int new_nice = kNiceValues[managed_priority - art::palette::kMinManagedThreadPriority];
int curr_nice = getpriority(PRIO_PROCESS, tid);
if (curr_nice == new_nice) {
return PALETTE_STATUS_OK;
}
if (new_nice >= ANDROID_PRIORITY_BACKGROUND) {
SetTaskProfiles(tid, {"SCHED_SP_BACKGROUND"}, true);
} else if (curr_nice >= ANDROID_PRIORITY_BACKGROUND) {
SchedPolicy policy;
// Change to the sched policy group of the process.
if (get_sched_policy(getpid(), &policy) != 0) {
policy = SP_FOREGROUND;
}
SetTaskProfiles(tid, {get_sched_policy_profile_name(policy)}, true);
}
if (setpriority(PRIO_PROCESS, tid, new_ni