Android Camera性能优化概述

目录

背景

一、性能优化关键点众览

二、性能关键技术

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性能优化方面的工作有几年了,想写一篇文章简单介绍一下其中涉及到的具体技术,这篇文章会大概介绍一下涉及到的技术。

一、性能优化关键点众览

     性能优化分析方向:给了多少资源和做了多少事。

  • 给多少资源主要是硬件方面资源,比如CPU频率、GPU频率、NPU频率、外设IO总线的clock、memory大小等,需要重点关注分配给当前task的资源,尤其是CPU时间片。在平衡功耗、内存和稳定性后应当最大化供给;
  • 做多少事主要是从软件角度触发,聚焦于业务逻辑的优化,以及整个系统的优化,不执行冗余代码,尽可能不阻塞关键路径和抢占其资源。
  • 达成目标:快且流畅,减少迟滞、波动(时快时慢)和不连贯(丢帧)给用户带来的心理落差。总结三个字就是:快、稳、省。
  • 优化建议:有全局观,抓主要矛盾,综合取舍。

二、性能关键技术

1. CPU调度

1.1 调度单位

线程是Linux的最小调度单位,而资源是以进程为单位进行分配和管理,包括程序(program text)、数据(data )、文件(open file)等,这些资源由同一进程下的线程共享。

1.2 线程状态

分析性能问题时,主要关注下面几种状态:

  • Running(R): 线程在正常执行代码逻辑
  • Runnable(R): 可执行状态,等待调度,如果长时间调度不到,说明CPU繁忙
  • Sleeping(S): 休眠,一般是在等待事件驱动
  • Uninterruptible Sleep(D): 不可中断的休眠,需要看Args的描述来确定当时的状态
  • Uninterruptible Sleep - Block I/O(D): IO阻塞

1.3 线程优先级

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

你可能感兴趣的:(camera专栏,#,camera软件,camera,性能优化,Android,Linux)