iOS 性能优化:Instruments
对于每位 iOS 开发者来说,代码性能是个避不开的话题。随着项目的扩大和功能的增多,没经过认真调试和优化的代码,要么任性地卡顿运行,要么低调地崩溃了之……结果呢,大家用着不高兴,开发者也不开心。
其实要破这个局面并不难,只要在 Xcode 自带的监控调试工具 Instruments 上花点功夫,让大代码流畅运行也不是神话。Instruments 提供了很多功能,我会重点介绍一下我最常用的三大类:
- Time Profiler:分析代码的执行时间,找出导致程序变慢的原因。
- Allocations:监测内存使用/分配情况
迅速膨胀的内存可以很快让程序毙命,所以要多加防范。 - Leaks:找到引发内存泄漏的起点
即使有 ARC(自动引用计数)内存管理机制,但在现实中对象之间引用复杂,循环引用导致的内存泄漏仍然难以避免,所以关键时刻还要自力更生。
针对这三方面的测试,在 GitHub 上,有个演示应用,来帮助大家更直观地了解这些工具的使用方法。好,进入正题。
Time Profiler
时间都去哪儿啦? Time Profiler 可以回答。它会按照设定的时间间隔(默认 1 毫秒)来跟踪每一线程的堆栈信息(stack trace),并通过比较时间间隔之间的堆栈状态,来推算出某个方法执行了多久,给出一个近似值。
在演示应用头一项「Time Profiler: System Methods」中,我用插入排序(Insertion Sort)和冒泡排序(Bubble Sort)两种算法来做性能比较,下面是 Swift 代码:
/* 引用自:http://waynewbishop.com/swift/sorting-algorithms/ */
func insertionSort() {
var x, y, key: Int
for (x = 0; x < numberList.count; x++) {
key = numberList[x]
for (y = x; y > -1; y--) {
if key < numberList[y] {
numberList.removeAtIndex(y + 1)
numberList.insert(key, atIndex: y)
}
}
}
}
func bubbleSort() {
var x, y, z, passes, key : Int
for (x = 0; x < numberList.count; ++x) {
passes = (numberList.count - 1) - x;
for (y = 0; y < passes; y++) {
key = numberList[y]
if (key > numberList[y + 1]) {
z = numberList[y + 1]
numberList[y + 1] = key
numberList[y] = z
}
}
}
}
这段代码主要是对数组的添加和删除,两种方法执行起来耗时不多,但后台发生的系统动作却多得让人眼晕。
可以发现,代码用到了很多间接依赖,这些都是支撑代码运行的系统库文件。因为处理大数据集比较消耗系统资源,所以要尽可能地把繁重的操作放到后台去做,上面的代码就走的后台线程。在上图的 Call Tree 中可以看到,被调用的堆栈名是 dispatch_worker_thread3。如果把它放到主线程去执行,程序肯定会挂起。不信你注释掉 dispatch_async 调用看一下。
再来个图片加载的例子。
这儿有三种图片加载方法:
- loadSlowImage1:从指定 URL 下载一张图片(加载速度慢)
- loadImage2:从本地资源库加载一张图片(注意:没用系统缓存)
- loadFastImage3:从系统缓存中加载一张图片(加载速度快)
我们来看看 Time Profiler 算出的结果是不是跟预想的一样。
进入演示应用第二项「Time Profiler: Our Methods」,点击「Reload」十次来重复加载图片,这样能产生足够的数据来分析。然后在 Time Profiler 图表中通过拖拉鼠标选中要放大查看的区域,从 Call Tree 中双击调用了 .reload 方法那一行(上图中加亮选中那一行),就会跳转到对应的代码行,所用时间也标注出来了。
看到谁最花时间了吧。虽然代码没什么可优化的地方,但大家应该认识到缓存能发挥的作用。所以即使有时还得调用 loadSlowImage,多数情况下把图片缓存下来,还是能省些资源占用。
此外,我想再说说 Call Tree 的选项设置。
这些选项默认是不选的,但把它们勾选上可以帮你更快定位到关键的代码上,往往这也是问题的源头。
- Separate by Thread:按线程分开做分析,这样更容易揪出那些吃资源的问题线程。特别是对于主线程,它要处理和渲染所有的接口数据,一旦受到阻塞,程序必然卡顿或停止响应。
- Invert Call Tree:反向输出调用树。把调用层级最深的方法显示在最上面,更容易找到最耗时的操作。
- Hide Missing Symbols:隐藏缺失符号。如果 dSYM 文件或其他系统架构缺失,列表中会出现很多奇怪的十六进制的数值,用此选项把这些干扰元素屏蔽掉,让列表回归清爽。
- Hide System Libraries:隐藏系统库文件。过滤掉各种系统调用,只显示自己的代码调用。
- Flattern Recursion:拼合递归。将同一递归函数产生的多条堆栈(因为递归函数会调用自己)合并为一条。
- Top Functions:找到最耗时的函数或方法。
需要添加其他工具的话:
Allocations
我们经常需要从服务器下载大量图片,特别是开发照片类的应用。但往往稍不注意,内存使用就会暴增,所以得保证把这些图片缓存下来以便重复使用。下面来看看演示程序中内存分配的例子。
从图中可以看到,每次点击「Reload」重新载入图片时,内存都会出现使用峰值。应用先分配大量内存来替换原有图片,然后再释放掉这部分内存,可想而知这样的操作效率高不了,而且如果要下载更大的文件,呃,局面大概会失控吧。
看一下堆栈列表第四行,ImageIO_PNG_Data 里有 9 张处于活动状态的图片,占用了12.38 MB 内存,这些都是没被系统释放或缓存的内存,所以导致堆内存分配升高。接下来再看看使用缓存后的效果。
使用了缓存库(Swift Haneke)后,点「Reload」五次,这回在 Allocations 列表中却看不到 ImageIO_PNG_Data 对象了,这说明它是空的,没有任何图像数据。同时,All Heap Allocations 的大小已从刚才的 14.61 MB 降到了 2.51 MB。Anonymous VM(匿名虚拟内存)是系统为程序预留的、可能会立即被重复使用的一部分可用内存。要防止程序崩溃,就别让堆的尺寸增长太快。
还有就是,例子用的是异步方式来加载图片,这样用不着等到所有图片下载完才能在界面中显示。大多数图像缓存库都会把加载工作放到后台,以避免延长主线程的响应周期。
Leaks
尽管 Apple 推出的 ARC 可以有效防范内存泄漏,但出问题的机率还是会有,Swift 也不例外。鉴于篇幅有限,本文就不涉及内存和 ARC 的工作原理了,具体可以参考官方文档。我会用代码来触发内存泄漏。
首先从最底层上说,当两个对象相互建立了强引用(strong reference),当一个对象被释放,另一个对象由于是强引用的关系不允许被释放,此时 ARC 无法确定没被释放的对象到底还有没有用,于是就导致了内存泄漏。
要解决这个问题,可以将其中的一个对象中变量设为 weak,不让它出现在保留周期中。很多开发者在管理 view controller 时常会在内存泄漏上中招,以为换了新的 controller,老的 controller 就被释放回收了,其实还没。这样代码一多,就会造成很多对象都没被释放。所以用这个工具把整个应用跑一遍,把那些断链的强引用清理干净,会大有裨益。
除了上述这三类工具,Instruments 还有很多实用的工具,推荐大家根据自己的关注点,花些时间去学学。比如:
- Core Data:监测读取、缓存未命中、保存等操作,能直观显示是否保存次数远超实际需要。
- Cocoa Layout:观察约束变化,找出布局代码的问题所在。
- Network:跟踪 TCP / IP和 UDP / IP 连接。
- Automations:创建和编辑测试脚本来自动化 iOS 应用的用户界面测试。
最后小总结下。如果应用跑得挺痛快,没出现啥调皮行为,大可把它忽略,等到问题来了再做优化。对于新手来说,花些时间了解 Instruments 的功能,多调试多积累经验,这样做出来的应用在用户体验上肯定错不了。
iOS 性能优化:Instruments的更多相关文章
- iOS性能优化:Instruments使用实战
iOS性能优化:Instruments使用实战 最近采用Instruments 来分析整个应用程序的性能.发现很多有意思的点,以及性能优化和一些分析性能消耗的技巧,小结如下. Instrument ...
- IOS 性能优化的建议和技巧
IOS 性能优化的建议和技巧 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelo ...
- iOS性能优化总结
iOS性能优化总结.关于 iOS 性能优化梳理: 基本工具.业务优化.内存优化.卡顿优化.布局优化.电量优化. 安装包瘦身.启动优化.网络优化等. 关于iOS 性能优化梳理: 基本工具.业务优化.内存 ...
- 【腾讯Bugly干货分享】微信读书iOS性能优化
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/578c93ca9644bd524bfcabe8 “8小时内拼工作,8小时外拼成长 ...
- iOS 性能优化收集
iOS 性能调试 instrument Instrument Instrument之Core Animation工具 避免图层混合 ①.确保控件的opaque属性设置为true,确保backgroun ...
- <转>iOS性能优化:Instruments使用实战
最近采用Instruments 来分析整个应用程序的性能.发现很多有意思的点,以及性能优化和一些分析性能消耗的技巧,小结如下. Instruments使用技巧 关于Instruments官方有一个很有 ...
- iOS - 性能优化:Instruments使用简介
最近采用Instruments 来分析整个应用程序的性能.发现很多有意思的点,以及性能优化和一些分析性能消耗的技巧,小结如下. Instruments使用技巧 关于Instruments官方有一个很有 ...
- iOS性能优化之内存管理:Analyze、Leaks、Allocations的使用和案例代码
最近接了个小任务,和公司的iOS小伙伴们分享下instruments的具体使用,于是有了这篇博客...性能优化是一个很大的话题,这里讨论的主要是内存泄露部分. 一. 一些相关概念 很多人应该比较了解这 ...
- iOS性能优化
最近采用Instruments 来分析整个应用程序的性能.发现很多有意思的点,以及性能优化和一些分析性能消耗的技巧,小结如下. Instruments使用技巧 关于Instruments官方有一个很有 ...
- 关于 iOS 性能优化方面的面试题,
这是我前面几天碰到的面试题: 如何对定位和分析项目中影响性能的地方?以及如何进行性能优化? 我的答案: 定位方法: instruments 在iOS上进行性能分析的时候,首先考虑借助instrum ...
随机推荐
- (转)swfobject.js 详细解说
一直想对这个应用做个总结,今天偶然百度到这个效果,为此做个笔记. 用这个js的好处: 1.IE中没有讨厌的虚框问题了.2.提供了完善的版本检测功能,如果版本不够则显示其他东西,比如图片或文字.3.易于 ...
- hadoop官网介绍及如何下载hadoop(2.4)各个版本与查看hadoop API介绍
1.如何访问hadoop官网?2.如何下载hadoop各个版本?3.如何查看hadoop API? 很多同学开发都没有二手资料,原因很简单觉得不会英语,但是其实作为软件行业,多多少少大家会英语的,但是 ...
- 利用反射动态构成sql语句
class Program { static void Main(string[] args) { People p = new Peo ...
- jQuery对checkbox的各种操作
//注意: 操作checkbox的checked,disabled属性时jquery1.6以前版本用attr,1.6以上(包含)建议用prop //1.根据id获取checkbox $("# ...
- mysql之7xtrabackup
目录: 1.前言 2.环境 3.开始备份 3.1.innobackupex介绍 3.2.一次完全备份 3.3.一次完全恢复 3.4.增量备份 3.5.增量备份的恢复过程 1.前言: Xtrabacku ...
- syslinux 3.84 2009-12-18 ebios copyright (c) 1994-2009 H. Peter Anvin et al
使用USB方式安装win7+Ubuntu12.04双系统时出现"syslinux 3.84 2009-12-18 ebios copyright (c) 1994-2009 H. Peter ...
- jsp执行数据库查询并分页
需求: 有一批企业的基本信息需要展示出来,要求一级页以列表形式展示企业清单,点击公司名称后进入二级页面,二级页面展示企业简介和几张图片. 实现效果: 开发环境: Win7,Eclipse,Mysql ...
- Blog透视镜
Blog透视镜,提供了Blog代码示例,文章和教程,可以帮助你建置博客. 网站名称:Blog透视镜 网站地址:http://blog.openyu.org
- sessionStorage 、localStorage 和 cookie 之间的区别(转)
essionStorage .localStorage 和 cookie 之间的区别(转) 2012-05-08 14:29:19| 分类: HTML5CSS3WEBAPP|举报|字号 订阅 ...
- Bulk-Only传输协议 UFI命令块规范
USB设备分为5大类,即显示器.通信设备.音频设备.人机输入和海量存储.通常所用的U盘.移动硬盘均属于海量存储类.海量存储类的规范中包括4个独立的子规范,即CBI传输.Bulk-Only传输.ATA命 ...