需要提前了解测试机跟对比机的一个参数差异,如CPU频率/GPU频率/memory size/分辨率等硬件配置及benchmark跑分情况,很多时候是因为某个硬件上的差异导致比对比机差,需要了解清楚
1、app版本是否相同
2、两个设备的起点、内容应该相同
3、DUT和REF尽量使用同一账号,排除显示内容不统一导致的问题
4、编译模式是否一致
5、滑动类问题联网后需手动滚动至少1分钟加载需测试内容[至少上下滚动5次]
1、刷新率是否一致
2、分辨率是否一致
3、设备温度是否基本持平
4、软件版本是否有差异
5、Driver Only
1、关闭蓝牙
2、关闭自动亮度
3、重启静置5分钟
4、实战屏幕超时时间为30分钟
5、开发人员选项中打开电源保持清醒
6、关闭其他应用后台、通知
7、关闭动画,包括:窗口动画缩放,过渡动画缩放,动画持续时间缩放
基本耗时可以直接看下面的思维导图进行分析,然后再到下面的CPU state进行分析:
Running 时间长,主要和CPU frequency及Task schedule策略有关系。
测试机跑低频,对比机跑高频?
①是否平台CPU架构本身差异--> 评估差异
②Boost CPU有效吗?--> power_app_list.xml适当调整DDR、DDR参数配置
③频率确认拉满了,确认是否存在限频的情况--> thermal、fpsgo、powerhal
对比机跑大核比例高,测试机跑大核比例小?
①CPU Loading情况?比对CPU Loading TOP 5进程(如JIT/heaptaskdaemon/kswapd等等)?--> TOP thread优化
②大核进程占用是否合理? --> 让UI Thread优先大核跑、优化大核占用线程
③其他耗时进程干扰?--> 优化无关线程的干扰
Boost DDR、GPU有效吗?有效 --> power_app_list.xml适当调整DDR、GPU参数配置
Android版本差异或者客制化差异导致?--> 借助traceview、simpleperf等工具辅助理清软件差异
Runnable时间长,主要和CPU Loading及Task schedule策略有关系。
①通过taskset命令
如果知道线程的pid,可以使用如下的命令查看这个线程允许运行的cpu:
taskset -p $pid //get the affinity of given PID
taskset -ap $pid //get the affinity of all threads of the PID
例如:# taskset -p 23378
pid 23378's current affinity mask: f
每一个cpu对应的一个bit位,cpu 0对应最低位。所以mask f 表示允许运行在cpu0-cpu3上面。
# taskset -ap 23378
pid 23378's current affinity mask: f
pid 23386's current affinity mask: f
pid 23387's current affinity mask: f
pid 23388's current affinity mask: f
pid 23389's current affinity mask: f
pid 23390's current affinity mask: f
②通过cat status查看Cpus_allowed
例如:# cat proc/1/status | grep Cpus_allowed
Cpus_allowed: ff
Cpus_allowed_list: 0-7
③systrace查看
抓取systrace如果带了sched_select_task_rq,那么在systrace中可以看到如下的信息:
其中mask表示pid=1272的task允许运行的cpu。
taskset -p cpumask $pid //set the affinity of given PID
taskset -ap $pid //set the affinity of all threads of the PID
例如,需要把renderthread固定到大核上面,可以使用命令:
实验绑小核:# taskset -p 0f 1
pid 1's current affinity mask: ff
pid 1's new affinity mask: f
# cat proc/1/status | grep Cpus_allowed
Cpus_allowed: 0f
Cpus_allowed_list: 0-3
在存在空闲CPU的情况下,优先选择空闲CPU进行调度。
a. 查询task所属的stune group
#cat /proc/[task PID]/cgroup
b. 针对对应group设定idle prefer属性
#echo 1 > /dev/stune/[cgroup]/schedtune.prefer_idle
c.查看idle prefer是否设定成功
#cat /dev/stune/[cgroup]/schedtune.prefer_idle
Boost CPU有效吗? --> 适当boost CPU
测试机存在其他异常背景进程(如JIT/heaptaskdaemon/kswapd等等)?--> 清除背景进程影响
Kswapd0的CPU占用率在TOP 3?检查Kswapd0 排名--> Low Memory 处理
Mmcqd/exe_cq的CPU占用率在TOP 3?检查mmcqd/exe_cq 排名 --> ,IO Issue处理
不存在Low Memory或者IO Issue --> TOP thread优化
Task的优先级及调度策略来自于继承或者特别设定,可以用来做判断依据,一般不建议做过多改动。
普通进程——renice指令
普通进程nice值范围是-20~19,对应priority的值是100~139,值越大优先级越低,默认nice值为0。可以用ps -el命令查看NICE值。
renice -n N –p $pid //将对应pid的thread,nice值加N,如果N为正数,那么优先级会变低;如果N为负数,优先级会变高
如果需要修改代码,建议使用setpriority()函数来调节普通进程的优先级
实时进程——chrt指令
实时进程的priority范围是1~99,值越小优先级越高(Kernel space)。可以用如下命令查看
chrt –p $pid //查看对应pid thread的scheduling priority和scheduling policy
chrt -p -f 10 $pid //将对应pid thread的调度策略设置为SCHED_FIFO,并将优先级设置为10
如果需要修改代码,建议使用sched_setscheduler来调节实时进程的优先级。
通过trace分析UI Thread休眠时间长,主要是等binder调用返回,再看具体binder在做什么操作,根据实际情况具体分析
查看前面的唤醒源是否合理,再根据Cpu state去分析唤醒源的情况。
检查IO数据量
IO数据量正常 --> IO Performance优化
IO数据量过大--> 参Low memory状况排查
没有Low Memory --> 澄清IO用量大的原因,如存在其他apk正在进行IO操作
调整内存相关的参数
1、明确卡顿的具体时间点,能够与测试提的卡顿对应起来
2、前提测试机不差于对比机
3、卡顿原因与无法改善原因的明确说明,对比机是否存在相同的卡顿。如测试机的卡顿原因有1、2、3,对比机只有1、2,需要详细说明为什么3只有测试机有,对比机没有,且1跟2也要体现出来,各项数据要充分
4、需要从Trace中体现滑动卡顿的iq、相关应用的BufferTX、trace的整体跟详细图、CPU的大小核与频率的情况、丢帧点需要框出来
5、说明无法优化的原因
【分析结论】
1、测试机跟与对比机一样存在中度抖动现象表现相当
2、抖动这段时间RenderThread没有跑,导致surfaceflinger没有buffer可以合成,属于apk自身问题
【Trace整体图】
测试机:
对比机:
【分析过程】
1、同步测试机的APK版本和连接相同网络测试,对比机一样存在中度抖动现象表现相当
2、测试机跟对比机都是在滑动快结束的时候有抖动,抖动这段时间RenderThread没有跑,导致surfaceflinger没有buffer可以合成,属于apk自身问题,应用自身问题测试机对比机行为一致,申请评估不解。
测试机:
对比机: