iOS性能检测优化

2019-07-06 » iOS性能优化

一、卡顿优化

卡顿的来源

iOS RunLoop是一个60fps的回调,也就是说每16.7ms绘制一次屏幕,有一次VSync 信号。RunLoop中的source都是队列执行,当你的事务执行超出刷新时间长度,在一个 VSync 时间内,CPU 或者 GPU 没有完成内容提交,则那一帧就会被丢弃,等待下一次机会再显示,而这时显示屏会保留之前的内容不变。这就是界面卡顿的原因。

1、检测

1、FPS 帧率检查,频繁低于60就说明有耗时问题。

DisplayLink做FPS检查帧率
CrashReporter 获取堆栈保存或者上报

2、RunLoop 主线程卡顿检查

RunLoop调用方法主要就是在kCFRunLoopBeforeSources和kCFRunLoopBeforeWaiting之间,还有kCFRunLoopAfterWaiting之后,也就是如果我们发现这两个时间内耗时太长,那么就可以判定出此时主线程卡顿

CrashReporter 可以收集堆栈,适用于开发阶段

<http://www.tanhao.me/code/151113.html/>

3、UI主线程监控

为了防止在子线程操作UI,我们在开发阶段hook掉UIView、CALayer的setNeedsLayout、setNeedsDisplay、setNeedsDisplayInRect:三个方法,当调用这三个方法时判断是否在主线程,如果不在主线程调用就让程序crash,在crash堆栈能看出是哪里的问题。

4、CPU占用率

CPU的使用也可以通过两种方式来查看,一种是在调试的时候Xcode会有展示,具体详细信息可以进入Instruments内查看,通过查看Instruments的time profile来定位并解决问题。另一种常见的方法是通过代码读取CPU使用率,然后显示在App的调试面板上,可以在Debug环境下显示信息,具体代码如下:

int result;
mib[0] = CTL_HW;
mib[1] = HW_CPU_FREQ;
length = sizeof(result);
if (sysctl(mib, 2, &result, &length, NULL, 0) < 0)
{
 	perror("getting cpu frequency");
}
printf("CPU Frequency = %u hz\n", result);
复制代码

2、优化方案

见前面的 iOS如何保持界面流畅

二、内存优化

1、检测

1、通过Instruments来查看leaks 、 Allocations

2、集成Facebook开源的FBRetainCycleDetector

3、集成MLeaksFinder

2、优化

iOS内存管理学习

1、循环引用导致的内存泄漏

通过 Instruments 或者 Xcode的内存图检查,然后处理,常见的处理方式:weak, weakProxy 弱化

2、另外就是大量数据加载及使用导致的内存警告。

虽然苹果并没有明确每个App在运行期间可以使用的内存最大值,但是有开发者进行了实验和统计,一般在占用系统内存超过20%的时候会有内存警告,而超过50%的时候,就很容易Crash了。所以内存使用率还是尽量要少,对于数据量比较大的应用,可以采用分步加载数据的方式,或者采用mmap方式。mmap 是使用逻辑内存对磁盘文件进行映射,中间只是进行映射没有任何拷贝操作,避免了写文件的数据拷贝。

三、启动优化

1、检测

Xcode本身支持启动耗时检测,在Edit Sceme 的Run - Arguments中添加Environment Variables: DYLD_PRINT_STATISTICS 并设置值为YES,且Diagnostics中开启 Dynamic Library Loads

我们需要统计两个指标:

1、main函数调用之前的加载过程的耗时 (动态库加载、资源加载耗时、load方法耗时)

2、main函数开始到app视图展示的耗时 (减少不必要的功能在这个时间段执行)

2、优化

iOS启动速度优化

四、包体积优化

1、检测

1、可执行文件大小

2、资源文件大小

减少一张图片就实实在在减少ipa包的大小

2、优化

1、图片资源优化

png 转 Webp、无损压缩、检测未使用的图片LSUnusedResource

2、文档资源优化

3、二进制包优化

无用的类、历史遗留业务、重复类型三方库

现在swift的swiftsupport已经被移到系统中,开启bitcode,本身就可以瘦身

分析LinkMap,查看那一部分占用空间大

https://ming1016.github.io/2017/06/12/gmtc-ios-slimming-practice/

五、电量、发热优化和其他优化

电量状态监测

也只有Instrument的电池监测更合适

https://mp.weixin.qq.com/s/q39BHIWsbdNeqfH85EOkIQ

性能优化要做的事

内存泄漏、卡顿、网络、CPU\GPU、电量\发热、启动速度、网络、包体积、编译

iOS 系统了解

可用性:crash abort bug

基础性能:启动时间、包体积

流畅:页面速度、卡顿、渲染

资源消耗:CPU 、内存、 流量、存储


AOP方式自动监控  页面跳转失败、Json解析失败、网络请求失败

埋点监控

1、性能监控 、量化需要优化的空间

卡顿的监控

监听主线程的方式来判断runloop执行时间统计,超时打印堆栈

消息发送时间统计

cpu大线程堆栈

启动时间优化:量化启动时间

https://www.jianshu.com/p/c14987eee107

https://techblog.toutiao.com/2017/01/17/iosspeed/#more

https://mp.weixin.qq.com/s/Kf3EbDIUuf0aWVT-UCEmbA

监测

优化

1、纯代码方式而不是storyboard加载首页UI。
2、对didFinishLaunching里的函数考虑能否挖掘可以延迟加载或者懒加载,需要与各个业务方pm和rd共同check 对于一些已经下线的业务,删减冗余代码。 
对于一些与UI展示无关的业务,如微博认证过期检查、图片最大缓存空间设置等做延迟加载
3、对实现了+load()方法的类进行分析,尽量将load里的代码延后调用。
4、上面统计数据显示展示feed的导航控制器页面(NewsListViewController)比较耗时,对于viewDidLoad以及viewWillAppear方法中尽量去尝试少做,晚做,不做。

2、性能优化

代码层面、事件处理、线程管理、I/O优化 NSCache

资源瘦身

png - webp (需要更多CPU解码时间)、重复资源监测、

性能优化

1、启动时间优化: 动态库、启动耗时检测、动态库加载时间检测、优化

启动的时候做了什么,有哪些地方是可以优化的。,动态库链接内存占用

2、FPS优化:App卡顿检测统计、流畅度优化

是哪些原因导致的卡顿,卡顿的可优化区间

CPU coreGraphics绘制耗时 GPU 渲染耗时

image展示优化,UIImageView 加载优化

YYAsyncLayer如何异步绘制? 原理

3、内存优化、内存的原理,虚拟内存等

3、耗电、发热优化:cpu和gpu使用的平衡

4、Xcode编译优化:xcode编译优化、代码风格优化、pod库自动脚本打成二进制库、

5、打包优化

理一理深层次的优化,系统层面、硬件原理层面

自动回收池原理

图片缓存 decode of images in the background

微信阅读优化

http://wereadteam.github.io/2016/05/03/WeRead-Performance/

app稳定性指标

https://juejin.im/post/58ca0832a22b9d006418fe43