本篇主要围绕Android性能优化,应用启动类性能问题为主题,先结合MTK的文档阐述应用启动流程,然后结合MTK的分析思路,其他厂商的思路,和我之前有段时间研究过某音的TOP300分析思路的案例,进行说明。
一、APP启动流程
所谓冷启动就是启动该应用时,后台没有该应用的进程,此时系统会为该应用创建新的进程,之后会bindApplication来创建程并初始化application, 然后通过反射执行ActivityThread中的main方法。
而热启动则是,当启动应用时,后台已经存在该应用的进程,比如启动该应用后,再按home 键反馈至主界面后,再打开该应用。此时会从已有的进程中来启动应用,这种方式不会重新走bindApplication的动作。
参考链接:https://online.mediatek.com/apps/quickstart/QS00157#QSS03755
1、启动前的准备
当我们点击桌面APP图标的时候,首先会调用launcher的onClick()方法,然后在桌面应用程序内部会通过添加intent.addflag(Intent.FLAG_ACTIVITY_NEW_TASK),调用Activity类的startActivity方法先pause前台的launcher,然后resume想启动想要启动的activity,直到新的应用程序启动成功,过渡动画结束为止。参考如下流程图:(PS:从MTK官方网站提取)

我们在看看如果一个应用启动,抓出来的trace是怎么样的呢?

仔细对比一下两者的差异,下面用文字进行解读和说明:
流程一:Launcher响应点击事件
当某应用程序在对某个activity声明MAIN和LAUNCHER之后,那么桌面应用程序Launcher就会把他们解析出来,对应图标排列在桌面。这样,用户就可以通过点击的方式启动Activity了。

当用户在桌面应用程序launcher上面点击某个应用ICON,那么launcher应用程序就得响应onClick事件,如何响应呢?

AMS通过ActivityStarter解析Intent和负责启动逻辑,然后与WMS进行交互握手,添加启动窗口(由addStartingWindow实现),这一步是为了解决"应用启动慢,屏幕会黑一下"的问题

参考如上泳图,launcher调用startActivityForResult,最终会走到AMS中,主要逻辑实现还得是调用startActivityUnchecked方法,去启动目标activity。
PS:这属于阶段一上半段流程
流程二:WMS启动过渡动画
接着上面的流程,AMS通知WMS调用StartingWindowEnterAnimation 方法启动窗口(Starting Window,俗称"白屏"或"预览屏")进入屏幕的动画阶段:
- 背景: 当用户点击 App 图标后,系统需要时间去 Zygote 进程 fork 出一个新的进程,并加载类、初始化 Application。这个过程通常需要几百毫秒甚至更久。
- 目的: 为了不让用户觉得"点击没反应"或者看到黑屏,WMS(Window Manager Service)会立即根据 App 的主题(Theme)创建一个临时的、轻量级的窗口。这个窗口通常只包含状态栏、导航栏和 App 的 Logo 或背景色。
- 动作: 圈红的部分表示 WMS 正在将这个临时窗口以动画的形式(通常是淡入或缩放)显示在屏幕上。这就是你在点击图标后,App 界面出来之前看到的那个瞬间画面。
当流程走到红框这一步时,WMS 已经完成了"准备"工作,并且正在屏幕上播放启动窗口的进入动画。这是 Step 1(响应时间)用户体验的关键组成部分------让用户感觉到系统已经迅速响应了点击操作。

PS:这属于阶段一下半段流程
流程三:应用焦点切换
startActivityUnchecked过程,还需要让界面从Launcher主界面切换为目标应用的主界面,因此需要做如下几件事情:
- Launcher应用顶层Activity走onPause流程

- AMS开始启动目标应用的主界面:resumeFocusedStackTopActivityLocked流程

如上就实现了应用界面的切换,从源应用(Launcher应用的acitity走暂停流程)切换到目标应用(resumeFocusedStackTopActivityLocked启动目标应用主界面)。
在resumeFocusedStackTopActivityLocked流程中可以了解到,如果目标应用进程不存在,就是冷启动流程,如果目标应用存在就是热启动流程。
- 热启动:如果目标应用进程存在,不需要Process.start
- 冷启动:如果目标应用进程不在,者调用Process.start最后走到zygote进程去创建fork子进程
2、冷启动
因为冷热启动后续流程基本一致,冷启动中间还需要通过zygote进程去fork子进程,所以先介绍冷启动:

如上流程,AMS走到了Zygote进程,fork子进程,然后调用子进程的main函数,main函数中主要就是对环境的一些初始化,最后创建上下文,最后回调bindApplication,这就完成了冷启动的第二阶段流程。
流程四:bindApplication/应用绑定阶段

如上流程图,这是应用启动的第一个阶段,系统创建 Application 实例并调用其 onCreate() 方法。具体做什么:
- 初始化应用级别的资源(图片、字符串、主题等)
- 初始化第三方 SDK(地图、统计、推送等)
- 初始化全局单例对象
- 设置全局配置(日志、Crash 采集等)
性能关注点:
- 常见问题: 很多开发者喜欢把所有初始化都放在这里,导致这个阶段特别长
- 优化方向: 懒加载、异步初始化、延迟非必要初始化
PS:bindApplication阶段其实对应于trace中的bindApplication

流程五:activityStart/Activity启动阶段

如上流程图, 从 bindApplication 完成后开始,到 onStart() 调用完成。具体做什么:
- 创建目标 Activity 实例
- 加载 Activity 的布局资源
- 绑定 View 控件(findViewById)
- 调用
onCreate()→onStart()
性能关注点:
- 常见问题: 布局层级过深、View 初始化过于复杂、主线程做耗时操作
- 优化方向: ViewStub 延迟加载、减少布局嵌套、异步加载数据
PS:activityStart阶段其实对应于trace中的activityStart

3、热启动
热启动因为不是第一次启动,所以他可以直接拿到进程PID,然后从activityStack拿到目标应用的主activity,直接回onResume即可。参考如下流程图:

如上流程图,热启动过程前面一致,最核心的就是AMS调用resumeTopActivity,直接拿到对于进程ID,然后直接调用acitvityResume和doframe等流程,这个过程中WMS依旧启动了过渡动画,只要目标应用的主界面绘制完成,就切换到目标应用的主activity中,完成了这次热启动。
流程六:activityResume/Activity 恢复阶段
从 onStart() 之后到 onResume() 调用完成。具体做什么:
- 调用
onResume()方法 - 准备开始绘制
- 恢复页面状态(如视频播放、动画等)
性能关注点:
- 常见问题: onResume 中做了太多耗时操作
- 优化方向: 把数据加载等操作放到异步线程
PS:activityResume阶段其实对应于trace中的activityResume

流程七:Choreographer#doFrame/第一帧绘制
这是应用启动完成的标志!系统开始第一次绘制 UI。具体做什么:
- 执行 View 的
measure(测量) - 执行 View 的
layout(布局) - 执行 View 的
draw(绘制) traversal就是整个绘制遍历过程
为什么这是启动结束的标志:
- 用户能看到内容了!这之前用户看到的还是启动窗口(白屏/黑屏)
- Google 官方定义:从点击到第一帧绘制完成就是完整的启动时间
- 第二帧(图中的 57395)不算在启动时间内,因为那已经是应用正常运行后的更新了
PS:doFrame阶段其实对应于trace中的Choreographer#doFrame

二、应用启动分析思路
MTK平台对这一类问题,详细输出了SOP,而其他厂商也分析思路也基本和这一致。
PS:本章内容主要摘抄MTK平台
1、对比机是否合理?
- CPU架构是否一样,CPU频率差异是否小于5%,L2/L3 cache是否一致?差异明显比较大的话,那不适合选取做对比机。
- ARM架构的差异可以去ARM官网参考: https://developer.arm.com/ip-products/processors/cortex-a
可以找到一些资料,比如:
https://developer.arm.com/Processors/Cortex-A710: Cortex-A710 brings an uplift of up to 10% in performance over Cortex-A78.
https://developer.arm.com/Processors/Cortex-A55: It delivers up to 18% more performance when compared to its predecessor, the Cortex-A53. - 在性能模式下,看antutu-CPU 和 geekbench 分数是否接近?如果跑分超过10%了,那也不太适合选取做对比机。
- ARM架构的差异可以去ARM官网参考: https://developer.arm.com/ip-products/processors/cortex-a
- DDR频率,MEM类型、读写速率对Launch Time、Activity切换等场景性能也会有影响,尽量确保MEM配置一致。
- 主要确认如下几件事情:
- 测试机与对比机是同一平台,并且硬件配置要一致,那么pass标准推荐为:测试机 不输 对比机即可。
- 测试机与对比机非同一平台,看benchmark差异如何,建议同步告知我们,让MTK把把关。
- 如果客户的QA有绝对指标,建议提供贵司的绝对指标依据,同配置的其他机器是否可以达标?
2、测试手法是否对齐?
测试前:
- 连网,app安装完成后首次启动,完成app的初始化设置(app权限设置、过场动画、登录账号等),等内容加载完成后在idle界面静置至少5min(避免初始化不sync状况),关闭应用自启动;
- 关闭APP,清除后台全部应用。
测试时:
- 断网;
- 关闭手机动画("设置→开发者选项→窗口动画缩放/过渡动画缩放/动画程序时长缩放"都关闭);
- 测试机和对比机最终测试画面保持一致。
起始点:手指离开屏幕 开始
结束点: APP 画面完全显示
注意事项:
- 如果手机重新开机,请等待10min后再进行测试;
- 冷启动测试前需要在"设置->应用->测试app的应用信息"中点击"force-stop APP";
- 退出app测试是按Back key 退到idle 界面;
3、Trace抓取与分析
Trace基本介绍可以参考如下链接:
打开systrace之后,先按ctrl+F搜索inputreader,找到systremserver下的inputReader 进程,然后再其运行状态中找到AppLaunch_dispatchPtr:Up的时间点,也就是手指离开屏幕的时间点。 然后找到启动的app 的UI thread,check 如下流程:
ActivityThreadMain
->bindApplication
->StartActivity
->activityResume
->Choreographer#doFrame ->draw
->RenderThread(DrawFrame)


4、根据CPU状态定位差异部分

确认running/sleeping/runnable/uninterruptible sleep时间长之后,根据后续内容进行分析。
5、MTK分析流程图

|--------|--------|-----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| No. || UX- 启动切换类分析 Flow | MOL 文档 |
| 分析前check项 ||| |
| 1 || 和对比机软硬体是否一致? | 对比机选取及目标设定 |
| 2 || 目标设定是否合理? | 对比机选取及目标设定 |
| 3 || 测试环境及手法是否与对比机对齐? | 常规测试场景-UX |
| 4 || 是否抓取测试机和对比机trace分析(确认trace有效性)? | Systrace获取及有效性确认 |
| 找到问题点 ||| |
| 5 || 与正常trace比对,确认过耗时在哪个步骤(am create/pause/stop/start/doframe)? | APP启动流程分析 |
| 6 || 与正常trace比对,确认过耗时在哪个cpu state(Running/Runnable/Sleep/Uninterruptible Sleep)? | APP启动流程分析 |
| 7 || Running state 分析 | Running时间长问题分析 |
| 7 | 7.1 | cpu freq有差异(测试机跑低频,对比机跑高频)? | Running时间长问题分析 |
| 7 | 7.1.1 | CPU设计本身Limitation? | CPU Limitation |
| 7 | 7.1.2 | 抓取带fpsgo及schedule信息的trace | perfconv抓取fpsgo以及schedule相关tag |
| 7 | 7.1.3 | 是否cpu能力给的不够? | 分析CPU频率是否正常 |
| 7 | 7.1.4 | 是否存在限频? | 分析CPU频率是否正常 |
| 7 | 7.2 | 查看大小核比例差异? | 大小核比例差异 |
| 7 | 7.2.1 | 是否有特别耗时的进程干扰? | CPU Loading确认 |
| 7 | 7.2.2 | 大核占用是否合理? | 优先级检查及调整 |
| 7 | 7.3 | DDR freq有差异? | DDR提频及频率信息抓取 |
| 7 | 7.3.1 | Boost DDR是否有效? | DDR提频及频率信息抓取 |
| 7 | 7.4 | SW-diff,是否为Android版本差异or客制化差异? | 通过trace或者更换Android版本先做初步厘清 |
| 7 | 7.4.1 | framework层往上 | traceview抓取方法 抓取apk启动过程的traceview |
| 7 | 7.4.2 | ART层差异 | 检查ART配置差异 ART heap properties |
| 7 | 7.4.3 | Native层往下 | simpleperf抓取方法 |
| 8 || Runnable state 分析 | Runnable State分析流程 |
| 8 | 8.1 | 请使用perfconv抓取schedule trace进一步分析 | perfconv抓取fpsgo以及schedule相关tag |
| 8 | 8.2 | 确认所在核为什么被别的task抢先执行? | Runnable State分析流程 |
| 8 | 8.2.1 | 抢占线程行为差异? | Runnable State分析流程 |
| 8 | 8.2.2 | 优先级低于抢占线程? | 优先级检查及调整 |
| 8 | 8.3 | 是否有其他空闲CPU可调度? | Runnable State分析流程 |
| 8 | 8.3.1 | 当前task是否绑核? | 检查绑核和设置perfer idle |
| 8 | 8.3.2 | 开启idle prefer 有效? | 检查绑核和设置perfer idle |
| 8 | 8.4 | CPU不空闲,loading重,boost有效? | CPU Loading确认 |
| 8 | 8.4.1 | 是否有异常背景进程? | CPU Loading确认 |
| 8 | 8.4.2 | Kswapd0的CPU占用率在TOP 3? | 检查kswapd0排名 Low Memory issue跳转10.3 |
| 8 | 8.4.3 | Mmcqd/exe_cq的CPU占用率在TOP 3? | 检查mmcqd/exe_cq排名 IO Issue跳转10.2 |
| 9 || Sleeping State 分析 | Sleeping State分析流程 |
| 9 | 9.1 | perfconv抓取schedule trace进一步分析,查找唤醒源(打开sched_waking与irq event) | perfconv抓取fpsgo以及schedule相关tag |
| 9 | 9.2 | 唤醒源是task? | 查找唤醒源分析 |
| 9 | 9.3 | 唤醒源是软/硬irq | 查找唤醒源分析 |
| 10 || Uninterruptible Sleep State 分析 | Uninterruptible Sleep State分析流程 |
| 10 | 查看Blocked reason是谁? || perfconv抓取fpsgo以及schedule相关tag |
| 10 | 10.1 | Block IO? | BlockIO相关 |
| 10 | 10.1.1 | IO数据量大? | BlockIO相关 |
| 10 | 10.1.2 | 是否有Low Memory? | LowMemory相关 |
| 10 | 10.1.3 | IO Performance差 | IO Performance优化建议 |
| 10 | 10.2 | Low memory引起的do_page_fault | Low Memory处理建议 |
| 10 | 10.3 | Other Block Reason | Uninterruptible Sleep State分析流程 |
6、MTK Running State分析
参考链接:Systrace 线程 CPU 运行状态分析技巧 - Running 篇 · Android Performance
参考链接:Mediatek Online
参考链接:Mediatek Online
如上链接已经详细的对CPU Running状态做了比较深入的介绍。因此如果和对比机存在明显的Running差异,那么可以认为CPU的执行能力不够,或者存在高负载情况影响了CPU的执行能力。

1)流程总结
依次check如下节点:
- cpu frequency差异:测试机跑低频,对比机跑高频?
是否平台CPU架构本身差异或者L2/L3 cache不一样?--> CPU Limitation
perfconv抓取trace进一步分析:perfconv抓取fpsgo以及schedule相关tag
Boost CPU有效吗?FAQ23670 Commands debug about CPU/GPU/DRAM/FPSGO/Thermal/Display
有效,是否CPU能力给的不够?分析CPU频率是否异常
能力没给够**--> 确认白名单配置,检查vendor/etc/power_app_list.xml 名单的设定,参数调校到和对比机表现一致。**
能力给够了,但是存在限频。 --> 排查限频原因
无效,继续往下确认。
- 大小核比例差异:对比机跑大核比例高,测试机跑大核比例小?
CPU Loading确认,比对CPU Loading TOP 5进程,测试机存在其他耗时进程抢占大核(如JIT/heaptaskdaemon/kswapd等等)?--> TOP thread优化
大核进程占用是否合理?
不合理 --> 优化大核占用线程
合理,继续往下确认。
- CPU频率和摆核无明显差异的情况下检查DDR频率差异
Boost DDR有效吗?FAQ23670 Commands debug about CPU/GPU/DRAM/FPSGO/Thermal/Display
有效 --> 适当调整DDR参数配置
如果发现无法Boost成功,需要检查PowerHal command是否执行成功,Kernel层需要DDR Owner check:
FAQ25729 用systrace方式抓取DDR频率、GPU频率和free memory等信息
Boost DDR无效,继续往下确认。
- Android版本差异or客制化软件差异
Android版本差异或者客制化差异导致(通过trace能直接找到差异点或者更换Android版本做初步厘清)?--> 澄清
借助traceview、simpleperf等工具辅助理清软件差异:
如果有ART层差异,检查ART配置差异。
- 若确认流程上无差异,且测试机和对比机的kernel版本有差异
check kernel overhead
- 综上可以总结如下
- 和对比机的CPU频率是否处于同一水平?
- 是否存在频率限制,是否存在温升限频率,针对单个进程提升CPU频率
- 是否存在其他进程抢占,大核占用率是否一致?
- 系统负载是否一致,是否存在优化空间?
- DDR没有遇到过,不是很熟悉
2)案例之CPU架构差异导致CPU Limitation
问题背景:查看systrace发现测试机 activityStart 为695.113 ms,对比机activityStart 为395.400 ms。activityStart 阶段差距300ms,其他阶段无差异。查看activityStart 测试机每个view绘制都比对比机要慢一倍。但是有如下重要信息:
- 测试机 :2大核 +6小核
- 对比机: 4大核+ 4小核
分析流程:从客户提供的systrace里面来看,rp.b612.android 这个process的UI thread的activityStart一共花费时间693.185ms 其中
- running: 591.569ms
- sleep: 88.844ms
- runnable:12.622ms
- uninterruptible sleep: 0.150ms
而对比机一共花费391.326ms,其中
- running: 286.901ms
- sleep: 58ms
- runnable:41.529ms
- uninterruptible sleep: 4.894ms
trace分析:所以从上面的数据来看,主要差距在running的时间测试机比对比机长300ms.从CPU的状态来看,当前已经跑在了最高频,但是因为rp.b612.android是多线程process,所以他偶尔会有线程跑到了CPU0/CPU1/or others CPU。
测试机每次跑到别的CPU上时,测试的两个大核CPU6/CPU7都是满载状态,所以也不存在CPU大小核调度问题,因为大核只有CPU6和CPU7,在大核满载的情况下,部分运行在其他小核上也属于正常现象。

对比机每次都运行在CPU4/5/6上面,刚好这款机型有四个大核。

分析结论:测试机只有CPU6和CPU7是大核,其他都是小核;然而对比机是4个大核+4个小核。不存在大小核抢占问题,所以原因只有一个,测试机的两个大核相比对比机四个大核能力不够。这个问题原因是测试机和对比机CPU架构不一样导致。
3)案例之CPU频率限制导致Running过长
详细参考https://online.mediatek.com/apps/quickstart/QS00157#QSS03745
这类问题直接check Clock Frequency 或者CPU Frequency即可:

4)案例之CPU大核占用率差异过大
详细参考Mediatek Online
这类问题直接计算对比两者之间的大核占用率即可,通常超过百分之二十(90%-70%)以上就很可疑:

5)案例之Android R和Q流程差异导致
详细参考:Mediatek Online
问题背景:R和Q应用冷启动对比(driveronly有相同情况),发现多个应用在R上出现两种情况:
- 应用启动流程不一致(CPU、DDR器件相同,频率最高的情况)
- 同样流程CPU运行时间不一致的情况,如:com.outfit7.talkingtom(CPU、DDR器件相同,频率最高的情况)
分析流程:从simpleperf里面看到,测试机R版本的memory行为总是比对比机Q上要多。所以怀疑是memory的问题,导致整个running时间长。
R测试如下

Q测试如下

因客户抓的simpleperf没有详细的信息,MTK这边自己用demo phone 测试了下,发现setvp8data和scudo都会调用__memcpy_a53,所以怀疑是scudo导致setvp8data调用时间长。即R不会走这个函数,Q会走这个流程,这个就属于在R和Q上,应用启动流程存在差异。
6)案例之Kernel 5.15因为GKI升级引入的kernel overhead导致衰退
详细参考:Mediatek Online
问题背景:在K515上有观察到app luanch time因为GKI升级引入的kernel overhead导致衰退,本分析guide适用于K510/k515/K6.x 等等。未来有其它原因导致差异,会再根据具体原因更新说明

这里介绍trace的方式进行拆解:
- 抓取准备:
adb shell "chmod 777 /sys/kernel/tracing/events/raw_syscalls/sys_enter/enable"
adb shell "chmod 777 /sys/kernel/tracing/events/raw_syscalls/sys_exit/enable"
adb shell "chmod 777 /sys/kernel/tracing/events/raw_syscalls/enable"
adb shell "ps -AT |grep trace"
获取traced_probes的Tgid, 然后kill
如tgid为19989 : adb shell "kill -9 19989"
- perfconv 勾选ftrace events → raw_syscalls/*

- 框选主线程的启动过程中所有的systrace tag, 计算sys_xx 的 Wall duration的时间 (注: 统计过程中,需去除sys_epoll_pwait 的相关统计)


7)案例之Android V冷启动时间远远差于U
问题背景:Android V 中冷启动时间从trace看差于U,且Speed、Speed Profile 均差于Android U phone。
分析流程:trace中有大量形如:Lp/nln; 这类的不明内容的trace tag打印
- 拆解trace,发现一个明显的差异是在ActivityStart 阶段,而且主要相差在Running时间
- 这种情况应该抓取simpleperf。使用如下命令抓取simpleperf:
bash
/system/bin/simpleperf record -g -e instructions:k,instructions:u --app com.spotify.music --duration 5 -o /sdcard/perf.data --call-graph dwarf --user-buffer-size 1G
发现二者instructions:k 有差距(2.4 * 10^9 vs 1.9 *10^9 ),但instuctions:u 相差很多 (1.7 * 10^9 vs 1.2*10^9),如果是和前面案例里接近的kernel overhead的影响,instructions:u 应该接近。
而instrucstions:u 的差距通常也会带来instructions:k 的差异。因此,此题的关键在于分析instructions:u。通常,instructions:u 的增长意味着应用本身的流程差异。但此题中,相差最大的是libart、libdex 和 libc:

可以看到,这三个ART 本身的so库,造成了几乎全部的instructions 增长。
进一步观察分析,libart和libdex中,增长最明显的是一些classlinker 方面的方法。而libc 中增加最明显的是vsnprintf 和 strlen ,可见是一些字符串处理方法。像是print。
对比trace发现,Android V的trace里由大量的"Landroidx/appcompat/widget/SearchView; "这样的打印。
这应该是一个函数名。函数名 + 打印,怀疑是这些instructions的打印造成了classlinker的耗时增加。
对比U和V的classlinker的代码,发现V上新增一行trace打印:
cpp
/art/runtime/class_linker.cc
return sdc.Finish(nullptr);
}
ScopedTrace trace(descriptor);
if (klass == nullptr) {
//这行trace 归属于Dalvik atrace event。这行log 在Android U上不存在。
- 从对齐trace event的角度逆推:

通过二分法排查Atrace event、和代码分析,发现Android V 的ART 比U上新增一行log。和前面正面分析结论一致。去掉dalvik event后,打印和U接近,时间也显著降低

分析结论:Android V有新增的Dalvik trace Event,导致大量trace 打印耗时。且Speed 编译模式下格外明显。U上无此trace。在当前的Android V 版本启动问题分析时,分析前期,如非必要,应避免抓取Dalvik event。
7、MTK Runnable State
参考链接:Systrace 线程 CPU 运行状态分析技巧 - Runnable 篇 · Android Performance
参考链接:Mediatek Online
参考链接:Mediatek Online
如上链接已经详细的对CPU Runnable状态做了比较深入的介绍。因此如果和对比机存在明显的Runnable差异,那么可以考虑CPU Loading负载及Task schedule调度策略有关系。

1)流程总结
依次check如下几点:
- perfconv抓取trace进一步分析
perfconv抓取fpsgo以及schedule相关tag
- 比较抢占线程差异:
所在核被什么线程抢占?抢占线程行为在测试机和对比机上有什么差异?--> trace确认,对齐抢占线程行为
抢占线程行为已对齐,那么是否当前线程优先级低于抢占线程?优先级检查及调整
可以调整优先级?--> 问题解决
优先级不能调整或者调整无效,继续往下确认。
- 存在其他空闲CPU可以调度?
存在空闲CPU,确认是否可以调度,当前task是否绑核?检查绑核和设置perfer idle
存在绑核行为 --> 解除绑核
开启prefer idle是否有效? --> 开启prefer idle
上述方法均无效,存在空闲CPU但是无法调度,请schedule owner介入check。
- 无空闲CPU,可能当前CPU Loading比较重,是否有优化空间?
Boost CPU有效吗?FAQ23670 Commands debug about CPU/GPU/DRAM/FPSGO/Thermal/Display
有效 --> 适当boost CPU
Boost无效,比对CPU Loading TOP 5进程,CPU Loading确认
测试机存在其他异常背景进程(如JIT/heaptaskdaemon/kswapd等等)?--> 清除背景进程影响
测试机无异常背景进程,排查是否存在Low Memory或者IO Issue:
Kswapd0的CPU占用率在TOP 3?检查Kswapd0 排名**--> Low Memory issue**
Mmcqd/exe_cq的CPU占用率在TOP 3?检查mmcqd/exe_cq 排名 --> ,IO Issue跳转10.2
不存在Low Memory或者IO Issue --> TOP thread优化
- 综上可以总结如下:
是否存在其他线程抢核,大核占用率是否存在差异?
是否存在绑核行为,能否提升该进程的优先级?
计算CPU的负载,看是否存在优化空间?
