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

1、前言

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

CPU使用率原理理解

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

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

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

先介绍几个和Linux时间有关的名词:HZtickjiffies

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占用率数据获取--第三方测试工具

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

CPU测试大家一般都使用外部提供的第三方工具来辅助测试,类似上方列举的这些、这些工具的原理都是基于调用 android 底层的一些 api 来获取到测试所用到的值,当然我们也可以采用其他方法,如使用 android 本身提供的一套 adb 即可完成上述测试。

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);

而这些变量的值,是在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占用走势情况

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 循环)

时间: 2024-11-05 20:45:18

Android App性能评测分析-cpu占用篇的相关文章

Android App性能评测分析-内存篇

1.内存了解 在Android App的性能优化的各个部分里,内存方面的知识较多且不易理解,内存的问题绝对是最令人头疼的一部分,需要对内存基础知识.内存分配.内存管理机制等非常熟悉,才能排查问题. 1.1 了解进程的地址空间 在32位操作系统中,进程的地址空间为0到4GB,这里主要说明一下Stack和Heap:Stack空间(进栈和出栈): 由操作系统控制,其中主要存储函数地址.函数参数.局部变量等等,所以Stack空间不需要很大,一般为几MB大小. Heap空间: 它的使用由程序员控制,程序员

Android App性能评测分析-网络流量篇

1. 前言 移动互联网发展到现在,虽然用户的联网方式已经完成了3G/4G网络依赖到Wifi依赖的转变,但是过多以及没有经过处理的网络请求,会消耗用户的网络流量,造成用户流量费用(金钱)的损失,高流量的消耗必然导致非WIFI场景用户的流失,流量测试在性能评测中势必会占较大的权重.下面会根据实际app性能测试案例,展开进行app性能评测之网络流量的分析和总结. 2. 流量测试方法 2.1 流量理解 运营商替我们的手机转发数据报文,数据报文的总大小(字节数)即流量,这里的数据报文包含手机上下行的报文.

Android App性能评测分析-启动时间篇

1.前言 随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,性能问题从应用的启动优化开始,下面会根据实际app性能测试案例,进行app性能评测之启动时间的分析和总结. 2.App启动方式了解 通常来说, 一个App启动也会分如下三中不同的状态: 冷启动 当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动,也就是先实例化Application 冷启动的流程即为App启动流程的全过程, 需要创建App进程, 加载

Pury — 一个新的 Android App 性能分析工具

本文讲的是Pury - 一个新的 Android App 性能分析工具, 手机应用存在的目的,就是在帮助用户做他们想做的事情的同时,提供最好的用户体验 -- 而用户体验的重中之重是应用的性能.但有时候开发者们却以性能为借口,既没有达到既定目标,又写着低质量并难以维护的代码.在这里我想引用 Michael A. Jackson 的一句话: "程序优化守则第一条:别去做它.程序优化守则第二条(仅限于专业人员):别去做它,现在还不是时候." 在开始任何优化之前,我们要先认清问题的症结所在.

移动App性能评测与优化

实战 移动App性能评测与优化 TMQ专项测试团队 编著  图书在版编目(CIP)数据 移动App性能评测与优化/ TMQ专项测试团队编著. -北京:机械工业出版社,2016.9 (实战) ISBN 978-7-111-54826-3 I. 移- II. T- III. 移动终端-应用程序–程序测试–研究 IV. TN929.53 中国版本图书馆CIP数据核字(2016)第213174号 本书通过六个专题方向介绍腾讯公司移动互联网事业群在移动应用性能评测优化方面的实战经验,涉及内存.电量.流畅度

优化Android App性能?十大技巧必知!

http://blog.csdn.net/qijianke2014/article/details/40041331 无论锤子还是茄子手机的不断冒出,Android系统的手机市场占有率目前来说还是最大的,因此基于Android开发的App数量也是很庞大的.那么,如何能开发出更高性能的Android App?相信是软件开发公司以及广大程序员们头疼的一大难题.今天,就给大家提供几个提高Android App性能的技巧. 高效地利用线程 1.在后台取消一些线程中的动作 我们知道App运行过程中所有的操

java-你的android app在运行过程中占用内存多少?

问题描述 你的android app在运行过程中占用内存多少? Hello,android开发不可避免的碰到内存管理,有时会碰到内存溢出的问题.因此谷歌对android系统的每个app做了内存限制,早期版本的android系统(比如1.5,1.6,2.1等),每个app的内存不能够超过32M.这个限制在android系统4.0开始就取消了,开发者在工程的AndroidManifest.xml中可以使用android:largeHeap="true"增加app对内存的使用限制. 我是做壁

Android App调试内存泄露之Cursor篇_Android

最近在工作中处理了一些内存泄露的问题,在这个过程中我尤其发现了一些基本的问题反而忽略导致内存泄露,比如静态变量,cursor关闭,线程,定时器,反注册,bitmap等等,我稍微统计并总结了一下,当然了,这些问题这么说起来比较笼统,接下来我会根据问题,把一些实例代码贴出来,一步一步分析,在具体的场景下,用行之有效的方法,找出泄露的根本原因,并给出解决方案. 现在,就从cursor关闭的问题开始把,谁都知道cursor要关闭,但是往往相反,人们却常常忘记关闭,因为真正的应用场景可能并非理想化的简单.

Android App调试内存泄露之Cursor篇

最近在工作中处理了一些内存泄露的问题,在这个过程中我尤其发现了一些基本的问题反而忽略导致内存泄露,比如静态变量,cursor关闭,线程,定时器,反注册,bitmap等等,我稍微统计并总结了一下,当然了,这些问题这么说起来比较笼统,接下来我会根据问题,把一些实例代码贴出来,一步一步分析,在具体的场景下,用行之有效的方法,找出泄露的根本原因,并给出解决方案. 现在,就从cursor关闭的问题开始把,谁都知道cursor要关闭,但是往往相反,人们却常常忘记关闭,因为真正的应用场景可能并非理想化的简单.