iOS 之 UITableView 性能优化(三)
前两篇文章中,我们已经详细介绍了 UITableView 的各种优化建议,那么下面我们一起来看看经过修改过后的 UITableView 优化程度到底如何。下面我们通过 Xcode 自带的调试工具 Instruments 来看看项目界面的流畅度,及其一些建议。
Instruments
Instruments 给我提供了各种各样的调试查看工具,下面简单介绍一下:
Blank: 创建一个空的模板,可以从 Library 库中添加其他模板.
Activity Monitor: 监控进程级别的 CPU,内存,磁盘,网络使用情况,可以得到你的应用程序在手机运行时总共占用的内存大小.
Allocations: 跟踪过程的匿名虚拟内存和堆的对象提供类名和可选保留/释放历史,可以检测每一个堆对象的分配内存情况.
Cocoa Layout : 观察 NSLayoutConstraint 对象的改变,帮助我们判断什么时间什么地点的constraint是否合理.观察约束变化,找出布局代码的问题所在.
Core Animation: 这个模块显示程序显卡性能以及 CPU 使用情况,查看界面流畅度.
CoreData: 这个模块跟踪 Core Data 文件系统活动.
Counters : 收集使用时间或基于事件的抽样方法的性能监控计数器 (PMC) 事件.
Energy Log: 耗电量监控.
File Activity: 检测文件创建,移动,变化,删除等.
Leak: 一般的措施内存使用情况,检查泄漏的内存,并提供了所有活动的分配和泄漏模块的类对象分配统计信息以及内存地址历史记录.
Metal System Trace: Metal API 是 Apple 2014年在 iOS 平台上推出的高效底层的 3D 图形 API,它通过减少驱动层的 API 调用 CPU 的消耗提高渲染效率.
Network: 用链接工具分析你的程序如何使用 TCP/IP 和 UDP/IP 链接.
SceneKit: 3D 性能状况分析.
System Trace: 系统跟踪,通过显示当前被调度线程提供综合的系统表现,显示从用户到系统的转换代码通过两个系统调用或内存操作.
System Usage: 这个模板记录关于文件读写, sockets, I/O 系统活动,输入输出.
Time Profiler(时间探查): 执行对系统的 CPU 上运行的进程低负载时间为基础采样.
Zombies: 测量一般的内存使用,专注于检测过度释放的野指针对象,也提供对象分配统计,以及主动分配的内存地址历史.
那这里我们就用 Instruments 中的第五个工具:Core Animation 进行检测。这个模块显示程序显卡性能以及 CPU 使用情况,查看界面流畅度。
首先我们必须要把 Demo 安装到测试设备上,快捷键 (Command + Control + i) 调出 Instruments,选择 Core Animation。打开后我们可以看到 Debug Options 里面有多个调试选项,下面我们挨个尽量来分析看一下:
Color Blended Layers
这个选项基于渲染程度对屏幕中的混合区域进行绿到红的高亮显示,越红表示性能越差,会对帧率等指标造成较大的影响,红色通常是由于多个半透明图层叠加引起。
演示项目比较简单,图层也不是很复杂,所以通过 Color Blended Layers 查看,深红色并不是很明显,在快速滑动的过程中,帧率依然能够保持在 55+ 以上,并且图层中也没有大量的深红色区域出现。
Color Hits Green and Misses Red
当 UIView.layer.shouldRasterize = YES 时,耗时的图片绘制会被缓存,并当做一个简单的扁平图片来呈现。这时候,如果页面的其他区块 (比如 UITableViewCell 的复用) 使用缓存直接命中,就显示绿色,反之,如果不命中,这时就显示红色。红色越多,性能越差。因为栅格化生成缓存的过程是有开销的,如果缓存能被大量命中和有效使用,则总体上会降低开销,反之则意味着要频繁生成新的缓存,这会让性能问题雪上加霜。
!)
说到这里,不得不提一下图片的加载方式,我们知道图片的一般加载方式有两种: imageNamed
和imageWithContentsOfFile
; 它们的不同在于前者会对图片进行缓存,而后者只是简单的从文件加载文件。如果你加载的是大图,并且只会用到一次,比如欢迎引导图,那么就没必要缓存这个图片,可以使用 [UIImage imageWithContentsOfFile:]
,用完就释放了。如果会多次使用到一张图时,用 [UIImage imageNamed:]
就会高效很多,因为这种加载图片方式有一个缓存机制。YYImage 实现原理应该就是后面这种思路,自己手动添加缓存。
Color Copied Images
对于 GPU 不支持的色彩格式的图片只能由 CPU 来处理,把这样的图片标为蓝色。蓝色越多,性能越差。因为,我们不希望在滚动视图的时候,由 CPU 来处理图片,这样可能会对主线程造成阻塞。
Color Immediately
通常 Core Animation Instruments 以每毫秒 10 次的频率更新图层调试颜色。对某些效果来说,这显然太慢了,这个选项就可以用来设置每帧都更新。 (可能会影响到渲染性能,而且会导致帧率测量不准,所以不要一直都设置它)
Color Misaligned Images
这个选项检查了图片是否被缩放,以及像素是否对齐。被放缩的图片会被标记为黄色,像素不对齐则会标注为紫色。黄色、紫色越多,性能越差。
这里 UI 在切图的时候尽量切得尺寸和你控件的尺寸保持一致,尽量让图片保持原始尺寸,这里所展示用图片几乎全部拉伸,由于图片都是从本地加载的,没有经过处理。
Color Offscreen-Rendered Yellow
这个选项会把那些离屏渲染的图层显示为黄色。黄色越多,表示性能越差。这些显示为黄色的图层很可能需要用 shadowPath 或者 shouldRasterize 来优化。
Color OpenGL Fast Path Blue
这个选项会把任何直接使用 OpenGL 绘制的图层显示为蓝色。蓝色越多,性能越好。如果仅仅使用 UIKit 或者 Core Animation 的 API,那么不会有任何效果。如果使用 GLKView 或者 CAEAGLLayer,那如果不显示蓝色块的话就意味着你正在强制 CPU 渲染额外的纹理,而不是绘制到屏幕。
后记
任何优化都是以业务需求为前提,在满足基本需求的情况下,逐步提高代码的质量,提升程序性能,不仅是自我能力的表现,也能从中获得一些收获及成就感。以上优化方向思路也是在前人总结的基础上,在项目中的简单应用,里面还有许许多多需要改进提升的地方,也希望大家能给一些深层次上的建议意见。
参考文章:iOS 保持界面流畅的技巧
原文链接:UIKit 性能调优实战讲解