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

简介: 1、前言很多时候在使用APP的时候,手机可能会发热发烫。这是因为CPU使用率过高,CPU过于繁忙,会使整个手机无法响应用户,整体性能降低,用户体验就会很差,也容易引起ANR等等一系列问题。

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

目录
相关文章
|
21天前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
2月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境对比分析
在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统无疑是主角。它们各自拥有独特的特点和优势,为开发者提供了不同的开发环境和工具。本文将深入浅出地探讨安卓和iOS开发环境的主要差异,包括开发工具、编程语言、用户界面设计、性能优化以及市场覆盖等方面,旨在帮助初学者更好地理解两大平台的开发特点,并为他们选择合适的开发路径提供参考。通过比较分析,我们将揭示不同环境下的开发实践,以及如何根据项目需求和目标受众来选择最合适的开发平台。
51 2
|
29天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
54 15
Android 系统缓存扫描与清理方法分析
|
15天前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
1月前
|
存储 Linux Android开发
Android底层:通熟易懂分析binder:1.binder准备工作
本文详细介绍了Android Binder机制的准备工作,包括打开Binder驱动、内存映射(mmap)、启动Binder主线程等内容。通过分析系统调用和进程与驱动层的通信,解释了Binder如何实现进程间通信。文章还探讨了Binder主线程的启动流程及其在进程通信中的作用,最后总结了Binder准备工作的调用时机和重要性。
Android底层:通熟易懂分析binder:1.binder准备工作
|
2月前
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
142 3
|
1月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境的差异性分析
【10月更文挑战第8天】 本文旨在探讨Android和iOS两大移动操作系统在开发环境上的不同,包括开发语言、工具、平台特性等方面。通过对这些差异性的分析,帮助开发者更好地理解两大平台,以便在项目开发中做出更合适的技术选择。
|
2月前
|
安全 Linux Android开发
探索安卓与iOS的安全性差异:技术深度分析
本文深入探讨了安卓(Android)和iOS两个主流操作系统平台在安全性方面的不同之处。通过比较它们在架构设计、系统更新机制、应用程序生态和隐私保护策略等方面的差异,揭示了每个平台独特的安全优势及潜在风险。此外,文章还讨论了用户在使用这些设备时可以采取的一些最佳实践,以增强个人数据的安全。
|
2月前
|
安全
【Azure App Service】App service无法使用的情况分析
App Service集成子网后,如果子网网段中的剩余IP地址非常少的情况下,会在App Service实例升级时( 先加入新实例,然后在移除老实例 )。新加入的实例不能被分配到正确的内网IP地址,无法成功的访问内网资源。 解决方法就是为App Service增加子网地址, 最少需要/26 子网网段地址。
|
2月前
|
IDE 开发工具 Android开发
安卓与iOS开发环境对比分析
本文将探讨安卓和iOS这两大移动操作系统在开发环境上的差异,从工具、语言、框架到生态系统等多个角度进行比较。我们将深入了解各自的优势和劣势,并尝试为开发者提供一些实用的建议,以帮助他们根据自己的需求选择最适合的开发平台。
49 1
下一篇
无影云桌面