<转>Android App性能评测分析-cpu占用篇

一、前言

不少时候在使用APP的时候,手机可能会发热发烫。这是由于CPU使用率太高,CPU过于繁忙,会使整个手机没法响应用户,总体性能下降,用户体验就会不好,也容易引发ANR等等一系列问题。如下会根据实际app性能测试案例,展开进行app性能评测之CPU使用率的分析和总结。html

CPU使用率原理理解

在Linux系统下,CPU利用率分为用户态、系统态、空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。java

平时所说的CPU利用率是指:CPU执行非系统空闲进程的时间 / CPU总的执行时间。android

那么咱们来看看这个时间到底是什么?shell

先介绍几个和Linux时间有关的名词:HZ、tick与jiffies。api

HZ:Linux 核心每隔固定周期会发出timer interrupt (IRQ 0),HZ是用来定义每一秒有几回timer interrupts。例如HZ为1000,就表明每秒有1000次timer interrupts。
Tick :Tick是HZ的倒数,Tick = 1/HZ 。即timer interrupt每发生一次中断的时间。如HZ为250时,tick为4毫秒(millisecond)。
Jiffies :在Linux的内核中,有一个全局变量:Jiffies。 Jiffies表明时间。它的单位随硬件平台的不一样而不一样。jiffies的单位就是 1/HZ。Intel平台jiffies的单位是1/100秒,这就是系统所能分辨的最小时间间隔了。每一个CPU时间片,Jiffies都要加1。 CPU的利用率就是用执行用户态+系统态的Jiffies除以总的Jifffies来表示。安全

CPU利用率计算公式也就是:
CPU使用率=(用户态Jiffies+系统态Jiffies)/总Jiffiesruby

二、CPU测试方法

2.1 CPU占用率数据获取--第三方测试工具

腾讯GT
平安云测试助手+评测中心(http://fit-stg1.jryzt.com/Hyperion-server/html/index.html) ---极力推荐
安测试
腾讯APT
网易Emageebash

CPU测试你们通常都使用外部提供的第三方工具来辅助测试,相似上方列举的这些、这些工具的原理都是基于调用 android 底层的一些 api 来获取到测试所用到的值,固然咱们也能够采用其余方法,如使用 android 自己提供的一套 adb 便可完成上述测试。网络

2.2 CPU占用率数据获取方法--adb命令

CPU是系统很是重要的资源,在Android中/proc/stat, 包含了全部CPU的相关详情信息,查看CPU使用状况,CPU不是一个瞬时态,而是一个过程态的体现,通常可使用top命令和dump cpuinfo命令进行CPU占用率获取。app

通常获取Android CPU数据的有两个命令:top和dump cpuinfo

2.2.1 top命令获取方法

(1)top命令方式获取原理了解:

top是比较经典的CPU计算方法,top的代码在androidm/system/core/toolbox/top.c下面,输出process的cpu使用率在print_procs里面,CPU的计算是proc->delta_time * 100 / total_delta_time

先看total_delta_time由:

total_delta_time = (new_cpu.utime + new_cpu.ntime + new_cpu.stime + new_cpu.itime + new_cpu.iowtime + new_cpu.irqtime + new_cpu.sirqtime)
  - (old_cpu.utime + old_cpu.ntime + old_cpu.stime + old_cpu.itime
  + old_cpu.iowtime + old_cpu.irqtime + old_cpu.sirqtime);

而这些变量的值,是在read_procs经过读取/proc/stat的jiffies获得:
因此总的cpu时间 = user + nice + system + idle + iowait + irq + softirq ,例如:User 147 + Nice 11 + Sys 79 + Idle 408 + IOW 1 + IRQ 0 + SIRQ 6 = 652
而proc->delta_time是两次读取/proc/pid/stat相减获得,可见,top是一段时间内,计算process的cpu jiffies与总的cpu jiffies差值获得。

附注释:

列名 描述
/proc/stat文件: 该文件包含了全部CPU活动的信息,该文件中的全部值都是从系统启动开始累计到当前时刻。不一样内核版本中该文件的格式可能不大一致。
user (147): 从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程。
nice (11): 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
system (79): 从系统启动开始累计到当前时刻,处于核心态的运行时间
idle (408): 从系统启动开始累计到当前时刻,除IO等待时间之外的其它等待时间
iowait (1): 从系统启动开始累计到当前时刻,IO等待时间(since 2.5.41)
irq (0) 从系统启动开始累计到当前时刻,硬中断时间(since 2.6.0-test4)
softirq (6): 从系统启动开始累计到当前时刻,软中断时间(since 2.6.0-test4)
(2)top命令获取CPU占用率实例:

adb shell top -m 100 -n 1 -s cpu | grep 包名

adb shell top -m 100 -n 1 -s cpu | grep com.pafinancialtech.fuzhoubank

zhangmeiyuan-5:~ zhangmeiyuan$ adb shell top -m 100 -n 1 -s cpu | grep com.pafinancialtech.fuzhoubank
18540  0  42% S   108 2102520K 317264K  fg u0_a858  com.pafinancialtech.fuzhoubank
 
CPU占用率_实时打印.png

 

 
CPU占用率_每隔5s打印一次.png

2.2.2 dump cpuinfo命令获取方法

(1)dump命令方式获取原理了解:

dump cpuinfo是Android特有的命令,dump cpuinfo命令的实如今androidm/frameworks/base/core/java/com/android/internal/os/ProcessCpuTracker.java类里面,方法是printCurrentState:
而printProcessCPU输出process CPU的使用状况:

private void printProcessCPU(PrintWriter pw, String prefix, int pid, String label,
            int totalTime, int user, int system, int iowait, int irq, int softIrq,
            int minFaults, int majFaults) {
        pw.print(prefix);
        if (totalTime == 0) totalTime = 1;
        printRatio(pw, user+system+iowait+irq+softIrq, totalTime);
...
}

user+system+iowait+irq+softIrq就是totalTime。 st变量的赋值,在collectStats里面,st.rel_utime 和 st.rel_stime仍是经过读/proc/pid/stat相减获得,而st.rel_uptime倒是经过 SystemClock.uptimeMillis()差值,并非跟top同样,经过proc/stat获得总CPU jiffies,

因此,进程的总Cpu时间processCpuTime = utime + stime + cutime + cstime,该值包括其全部线程的cpu时间。(例外,通常cpu按100%计算,若是是多核状况下还需乘以cpu的个数)

附注释:
/proc/pid/stat文件:
该文件包含了某一进程全部的活动的信息,该文件中的全部值都是从系统启动开始累计 到当前时刻。
Utime(39) 该任务在用户态运行的时间,单位为jiffies
Stime(25) 该任务在核心态运行的时间,单位为jiffies
Cutime(0) 全部已死线程在用户态运行的时间,单位为jiffies
Cstime(0) 全部已死在核心态运行的时间,单位为jiffies

(2)dump命令获取CPU占用率实例

adb shell dumpsys cpuinfo |grep 包名

zhangmeiyuan-5:~ zhangmeiyuan$ adb shell dumpsys cpuinfo |grep com.pafinancialtech.fuzhoubank 117% 16322/com.pafinancialtech.fuzhoubank: 106% user + 11% kernel / faults: 45403 minor 99 major 0.5% 14032/com.pafinancialtech.fuzhoubank:pushservice: 0.5% user + 0% kernel / faults: 1610 minor +0% 16547/com.pafinancialtech.fuzhoubank:remote: 0% user + 0% kernel 
 
CPU_dump方式获取的占用率.png

 

从上图咱们能够看出:80%是针对这个CPU的占用率是80%,其中72%占用率是用户使用的,8.4%是内核的占用率,这个数只是针对1核来讲,如今手机都是多核的了,那这样的值也不会太准确,若是是多核状况下还需除以cpu的个数。

综上:top跟dump cpuinfo的区别在于:top分母是总测CPU jiffies,而dump cpuinfo是是时间,而并不是jiffies,也能解释为何top出来的cpu,大部分时间会比dump cpuinfo小的缘由。

2.3 CPU问题分析思路及工具

若是APP某场景进行操做时出现发烫、卡顿、ANR现象时,能够怀疑出现CPU问题,通常解决思路以下:

a. 若是已经致使ANR, 则去log里面搜索"ANR in"
b. 没有致使ANR则基于以上方法获取到的CPU占用率,若是某场景的CPU占用率走势异常、峰值存在异常、均值大于基线,则能够利用DDMS查看分析Trace文件,或者使用Android studio里面的Android Monitor根据Monitor中的CPU能够看出目前CPU明细使用。
c.查找程序中有没有特殊布局或者特殊操做(GPS定位,一直刷新类的服务等),特殊加载(Gif图片加载,视频,音频加载等)

2.3.1 Android Monitor监控分析

拿到APP源码,在Android studio中构建测试DEBUG包进行调试以下截图:

 

 
cpu_monitor.png

 

 
image.png

双击我绿色框标记的这个按钮,就会生成这么一个文件,如图:

 

 
image.png

 

上图就一目了然的看到了耗费CPU 都有哪些方法。此时点击黑色的文本,几秒钟后studio会生成.trace文件,咱们就能够分析各方法使用cpu的状况了。

2.3.2 分析TraceView文件查找CPU问题

TraceView 是 Android SDK 中内置的1个工具,它能够加载 trace 文件,用图形的情势展示代码的履行时间、次数及调用栈,便于咱们分析。

(1)使用Android Studio工具DDMS

生成Traceview 进行分析查看具体Trace期间各方法调用关系,调用次数以及耗时比例

 

 
DDMS_查看各方法调用及CPU信息.png

附注释:
Traceview 面板分上下两部分
上面是时间轴面板 (Timeline Panel)
左侧显示的是线程信息
右侧黑色部分是显示执行时间段、白色是线程暂停时间段,
右侧鼠标放在上面会出现时间线纵轴,在顶部会显示当前时间线所执行的具体函数信息
下面是分析面板(Profile Panel) - 每一列内容
Inclusive time - 函数自己运行花费时间 + 函数调用其余函数时间
Exclusive time - 函数自己运行花费时间。
Calls + RecurCall/Total 调用 + 重复调用次数 / 函数总调用次数
Cpu Time/Call 总的Cpu时间与总的调用次数之比

附: Profile Panel各列做用说明

列名 描述
Name 该线程运行过程当中所调用的函数名
Incl Cpu Time 某函数占用的CPU时间,包含内部调用其它函数的CPU时间
Excl Cpu Time 某函数占用的CPU时间,但不含内部调用其它函数所占用的CPU时间
Incl Real Time 某函数运行的真实时间(以毫秒为单位),内含调用其它函数所占用的真实时间
Excl Real Time 某函数运行的真实时间(以毫秒为单位),不含调用其它函数所占用的真实时间
Call+Recur Calls/Total 某函数被调用次数以及递归调用占总调用次数的百分比
Cpu Time/Call 某函数调用CPU时间与调用次数的比。至关于该函数平均执行时间
Real Time/Call 同CPU Time/Call相似,只不过统计单位换成了真实时间

(2)使用代码生成 trace 文件

Debug.startMethodTracing("shixintrace");   
 //开始 trace,保存文件到 "/sdcard/shixintrace.trace"
    // ...
    Debug.stopMethodTracing();    //结束

代码很简单,当你调用开始代码的时候,系统会生产 trace 文件,而且产生追踪数据,当你调用结束代码时,会将追踪数据写入到 trace 文件中。
下1步使用 adb 命令将 trace 文件导出到电脑:

adb pull /sdcard/shixintrace.trace /tmp

使用代码生成 trace 方式的好处是容易控制追踪的开始和结束,缺点就是步骤略微多了一点。

2.3 CPU测试场景

通常cpu检测咱们要分4种状况:
1.在空闲时间的消耗,基本没大应用使用cpu

若是APP在退出界面后还有进程长期运行,那须要关注下待机场景的CPU。待机场景下CPU的消耗通常不会很大,例如福州直销银行APP在后台运行时,可能消耗常常是0%,长时间平均下,可能只有0.1%、0.2%,看看竞品,也是差很少,好像没有太大区别。那么CPU消耗这么少是否是就不用管CPU了呢,然而即便是平均值很小,可是长时间待机,例如安全类工具,CPU的消耗仍是不容忽视。
这种场景下咱们测试时经常使用的单位有:消耗XX jiffies/分钟;半/1小时共增长XX jiffies。

2.在运行一些应用的状况下,cpu已占50%的状况下,观察应用程序占用cpu的状况

简单说这种状况就是后台已经有几个应用在运行已经而且消耗了系统的一些资源的状况下进行测试。

3.在高负荷的状况下看CPU的表现,我定义这个高负荷,cpu占用应是在80%以上

满规格状态下的应用CPU消耗状况

4.观察App 相同/不一样场景下CPU走势、峰值状况

对比不一样场景页面CPU占用大小
对比不一样时间段同一场景页面CPU占用走势状况

三、XX银行性能评测-CPU测试结果分析

3.1 总览

这次质量开放平台-评测中心(http://fit-stg1.jryzt.com/Hyperion-server/html/index.html)的性能测试的采集的CPU占用数据主要是针对场景页面的CPU占用测试,CPU占用数据获取原理是CPU执行非系统空闲进程的时间 / CPU总的执行时间。

从CPU消耗对比来看,行业竞品均值为8.4%,90分位约4.9%,75分位约7.8%,中位数约9.3%,25分位约16.2%。

 

 
CPU占用对比.png

【榕商Bank】和10家竞品分析对比,CPU占用12.0%,表现较差,不及行业平均水准。可是从APP本品各场景CPU占用率来看,占用率最大的为理财产品详情页22.7%,主要缘由是该页面存在6个不一样时段近七日和万份收益率曲线走势图绘制,可是仍然未超过CPU占用率基线30%,且目前大部分手机是四核、八核系统,因此目前测试数据代表总体表现良好不存在瓶颈,可是从行业标准来看,理财产品详情页仍然有优化空间,建议优化。

 

 
理财产品详情页性能曲线.png

四、App端CPU问题排查思路:

(1)是否有很是多的网络请求
(2)是否开了不少进程OR 应用,尝试关闭其余应用再查看CPU是否降下来
(3)是否有大量大图片、视频处理跟加载或布局
(4)查找程序中有没有特殊布局或者特殊操做(GPS定位,一直刷新类的服务等),特殊加载(Gif图片加载,视频,音频加载等)
(5)当前页面是否有过多的图表、曲线图等绘制操做
(6)经过Android Studio 自带的monitor查找是哪一个Activity或者哪一个方法有一直不中止的运算消耗CPU(好比:不中止的while 或者for 循环)

 
 
 做者:萧竹 出处:https://www.jianshu.com/u/88caeb7696f5  本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接。
相关文章
相关标签/搜索