iOS性能检测指标
需求描述:
APP性能问题是造成App用户流失的罪魁祸首之一。调研的主要内容是定性APP性能的测试指标,对比目前项目中记录的数据,后续提供一些针对指标的优化方式,以供参考!
功能描述:
- APP性能检测指标考虑方向
- APP性能检测指标定性
APP性能检测考虑方向:
![](https://img.haomeiwen.com/i2907785/0ba2c91bc4142f54.png)
方向 —> 指标 :
1、CPU占用率:CPU占有率过高,会影响APP的流畅性,造成卡顿及运行速度降低!
影响CPU占有率:
- 对象创建:
对象的创建
会分配内存、调整属性、甚至还有读取文件等操作,比较消耗 CPU 资源。 - 对象调整:
对象的调整
也经常是消耗 CPU 资源的地方; - 对象销毁:对象的销毁虽然消耗资源不多,但累积起来也是不容忽视的。
- 布局计算:
视图布局的计算
是 App 中最为常见的消耗 CPU 资源的地方; - Autolayout:Autolayout 是苹果本身提倡的技术,在大部分情况下也能很好的提升开发效率,但是 Autolayout 对于复杂视图来说常常会产生严重的性能问题;
- 文本计算:
文本的宽高计算
会占用很大一部分资源,并且不可避免; - 文本渲染:屏幕上能看到的所有文本内容控件,包括 UIWebView,在底层都是通过 CoreText 排版、绘制为 Bitmap 显示的。常见的文本控件 (UILabel、UITextView 等),其排版和绘制都是在
主线程进行
的,当显示大量文本时,CPU 的压力会非常大; - 图片解码:当你用 UIImage 或 CGImageSource 的那几个方法创建图片时,图片数据并不会立刻解码。图片设置到 UIImageView 或者 CALayer.contents 中去,并且 CALayer 被提交到 GPU 前,CGImage 中的数据才会得到解码。这一步是发生在主线程的,并且不可避免。如果想要绕开这个机制,常见的做法是在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片。目前常见的网络图片库都自带这个功能;
- 图像的绘制:图像的绘制通常是指用那些以 CG 开头的方法把图像绘制到画布中,然后从画布创建图片并显示这样一个过程。这个最常见的地方就是 [UIView drawRect:] 里面了。由于 CoreGraphic 方法通常都是线程安全的,所以图像的绘制可以很容易的放到后台线程进行;
监控指标设置
:在页面加载时
监控CPU的占用率,以获取CPU的数据!相关的参数:CPU 频率
,CPU 最大频率
和 CPU 最小频率
。
2、FPS监控/卡顿:FPS是Frames Per Second 的简称缩写,意思是每秒传输帧数,也就是我们常说的“刷新率(单位为Hz);
FPS是测量用于保存、显示动态视频的信息数量。每秒钟帧数愈多,所显示的画面就会愈流畅,FPS值越低就越卡顿
,所以这个值在一定程度上可以衡量应用在图像绘制渲染处理时的性能。一般我们的APP的FPS只要保持在 50-60之间
,用户体验都是比较流畅的。
屏幕显示图像的原理:
![](https://img.haomeiwen.com/i2907785/b6504754542fc0d8.png)
具体原理:https://www.jianshu.com/p/0b58ac8e315d
造成卡顿的原因:
![](https://img.haomeiwen.com/i2907785/f845b1d618f45336.png)
如果在一个VSync 时间内,CPU 或GPU 没有完成内容提交,则那一帧就会被丢弃,等待下一次机会再显示,而这时显示屏会保留之前的内容不变。例如在主线程里添加了阻碍主线程去响应点击、滑动事件、以及阻碍主线程的UI绘制等的代码,都是造成卡顿的常见原因。
监控指标设置
: 两种实现方案
1)、 主线程卡顿监控。通过子线程监测主线程的runLoop
,判断两个状态区域之间的耗时是否达到一定阈值。-- 通过采用检测主线程每次执行消息循环的时间,当这一时间大于规定的阈值时,就记为发生了一次卡顿的方式来监控
2)、 FPS监控。要保持流畅的UI交互,App 刷新率应该当努力保持在 60fps
以上。
具体参考文献:
3、启动时长监控
Xcode 提供了测量启动时长的方法:
- Xcode 测量 pre-main 时间 方法: 只需要在
Edit scheme
-->Run
-->Arguments
中将环境变量DYLD_PRINT_STATISTICS
设为 1,就可以看到main
之前各个阶段的时间消耗。
测量pre-main时间…
- 详细测量方式:
DYLD_PRINT_STATISTICS
换成DYLD_PRINT_STATISTICS_DETAILS
测量pre-main详细时间…
查看以上参数分析, 影响APP启动时长参数如下:
![](https://img.haomeiwen.com/i2907785/1869195832052ff1.png)
- dyld 会初始化动态库
- Rebase/Bind 相关资源
- 加载 object - 对象
- initializer : 方法加载
监控指标设置
:可针对以上参数监控APP,例如:对象的创建数量
;及时合并动态库
;监控initializer
方法时长;
详细参照:如何精确度量 iOS App 的启动时间
4、耗电量监控:监控APP的电量使用情况
获取当前电量:
UIDevice *device = [UIDevice currentDevice];
device.batteryMonitoringEnabled = YES;
//UIDevice返回的batteryLevel的范围在0到1之间。
NSUInteger batteryLevel = device.batteryLevel * 100;
//获取充电状态
UIDeviceBatteryState state = device.batteryState;
if (state == UIDeviceBatteryStateCharging || state == UIDeviceBatteryStateFull) {
//正在充电和电池已满
}
监控指标设置
:APP使用时间 + 电量记录
5、内存使用监控:监控APP的内存使用情况
内存使用情况监控非常简单,但是转化成具体监控内容或指标,提高监控的精确度相对复杂,其核心是追踪对象的生命周期,查看是否有内存泄漏
!查找循环引用链
!
1、追踪对象的生命周期
* 单例或者被 cache 起来复用的 View 或 ViewController
* 释放不及时的 View 或 ViewController
* 单例或者被 cache 起来复用
* 释放不及时
* 真正的内存泄漏
2、查找循环引用链
监控指标设置
:单例、block、对象监控
6、网络状况监控:监控APP的网络使用情况
网络监控一般通过 NSURLProtocol
和代码注入(Hook)
这两种方式来实现,由于 NSURLProtocol
作为上层接口
,使用起来更为方便,因此很自然选择它作为网络监控的方案,但是 NSURLProtocol
属于 URL Loading System
体系中,应用层的协议支持有限
,只支持 FTP,HTTP,HTTPS 等几个应用层协议,对于使用其他协议的流量则束手无策,所以存在一定的局限性。监控底层网络库 CFNetwork
则没有这个限制。
下面是网络采集的关键性能指标:
- TCP 建立连接时间
- DNS 时间
- SSL 时间
- 首包时间
- 响应时间
- HTTP 错误率
- 网络错误率
- 流量
监控指标设置
:请求时长、DNS、首包时间、响应时间、URL数量、响应码、流量大小
参考资料:iOS-Monitor-Platform