安卓Trace分析(CPU状态篇)
1.前言
在这段时间的分析trace学习中,刚开始总是不会有条理的分析,想到一处是一处,这导致分析的有可能不全面,也会影响自己的学习情况,于是写下这篇笔记。
帮助我在分析时能更加全面。
2.准备工作
这里我们就以常用的冷启动作为一个例子吧。由于只是概述流程,所以并不涉及具体分析。
我习惯先圈出总的区域,以便快速定位
接着,圈出三方应用UI线程的cpu状态:
从这里可以很清楚的看出cpu状态的差异,当你看完这篇文章之后,相信你在这一阶段,就有了大概的判断。
3.Running状态分析
3.1 软件版本
有可能是软件版本不同导致执行流程或者代码复杂度不同导致。
3.2 编译方式
有可能是编译方式不同导致时长不一致,这部分可以查看下面的blog进行学习
安卓Art编译方式 | Arden の 勇者聚集地 (ardenlee.love)
3.3 以解释方式运行
首先我们要有一个大致理解,一般有三种程序运行方式:
解释执行
源代码或字节码在运行时逐条被解释器解释执行,不进行预先的编译。可以理解为,安装快,启动运行慢。
当在trace中发现了大量 Compiling 字眼时有可能是处于解释方式运行。
编译执行
程序在运行之前将源代码或字节码一次性编译成本地机器码,然后直接执行编译后的机器码。比如我们很常见的 dex2oat 。
及时编译
介于解释执行和编译执行之间的一种方式,不属于传统的编译执行,但也不同于解释执行。它是一种动态编译技术,可以在一定程度上提高程序的执行效率,比如常见的 jit。
3.4 跑小核
小核可能性能达不到我们的需要,这时可以与对比机比较,看是否调度出现问题。
3.5 跑大核,频点低
是否是限频?如果不是限频,为什么频点没拉起来?
如果是限频,是否是温控限频,省电精灵限频。
可以查看对比机log大致判断对比机温控策略是否比测试机激进。
3.6 温升导致拔核
确定是否环境引起
是否是一些发热严重的器件导致的,比如是不是 cpu负载太高,对比机是否由于负载较低所以温度较低无拔核状态。
4.Runnable状态分析
同一时刻 CPU 只能跑一个线程,当一个任务准备好只差 cpu资源时的状态,所有的 running 执行前一定有一个 runnable 状态。
4.1 优先级设置问题
某一个线程设置过高,或过低,会导致自己抢占别的线程CPU资源或者,别的线程抢占该线程的CPU资源。
4.2 绑核问题
现在的机器,一般会将重要线程,比如surfacefliger,前台UI线程绑大核,主要还是和对比机来看绑核策略是否一致。
4.3 锁
系统线程锁或者应用自身锁
5.Sleeping状态分析
他们都是处于睡眠状态,拿不到 CPU的时间片,只有满足某些条件时才会拿到时间片,即变为 Runnable,随后是 Running。
Sleeping状态一般是由程序主动等待某个事件发生造成的,比如锁等待。
5.1 Binder耗时长
如果发现binder时间长,我们需要查看对端binder,是否是跑小核?是否是优先级问题,等等。
5.2 锁竞争
这类情况在整机负载高情况下容易出现。
5.3 等待
有可能会出现主线程等在渲染线程导致sleeping,渲染线程处理太慢导致sleeping耗时长。
6.不可中断睡眠状态分析
6.1 non-io
6.1.1 低内存等待
低内存的时候要回收其他程序或者缓存上的内存,有可能导致内存命中率问题,或缺页等。
6.1.2 Binder等待
6.1.3 内核锁
6.2 io
6.2.1程序大量读写
6.2.2 多线程都需要io操作
6.2.3 swap
开启 Swap 机制的内核下,数据从 Swap 中读取
开启swap机制之后,当系统内存不足时,部分不常用的数据会被移动到Swap分区,同时释放物理内存,当需要从Swap中读取数据的时候,触发页面置换,之后进行相应的操作。
这个功能不怎么开启
内存置换和swap是有区别的。