Android 性能测试 - CPU

1、前言

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

CPU使用率原理理解

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

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

那么我们来看看这个时间究竟是什么?
先介绍几个和Linux时间有关的名词:HZ、tick与jiffies。

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)/总Jiffies

2、CPU测试方法

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

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

(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 
auto:auto$ 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占用率_实时打印
CPU占用率_5s间隔

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 包名

auto:auto$ 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方式获取的占用率

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
cpu_monitor

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

cpu_monitor

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

2.3.2 分析TraceView文件查找CPU问题

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

(1)使用Android Studio工具DDMS

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


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

附注释:
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占用走势情况

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

3.1 总览

性能测试的采集的CPU占用数据主要是针对场景页面的CPU占用测试,CPU占用数据获取原理是CPU执行非系统空闲进程的时间 / CPU总的执行时间。

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

CPU占用对比

CPU占用对比.png

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

理财产品详情页性能曲线

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349