1、前言

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

CPU使用率原理理解

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

那么我们来看看这个时间究竟是什么?

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

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

2、CPU测试方法

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

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

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

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

一般获取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);
/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,

(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的个数。

2.3 CPU问题分析思路及工具

如果APP某场景进行操作时出现发烫、卡顿、ANR现象时,可以怀疑出现CPU问题,一般解决思路如下:

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

附: 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

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

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

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

3、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

4、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  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
01-19 12:41