一、简介
性能调优的方式可以分为:
- 通过专门的性能调优工具;
- 通过代码优化;
二、内容
1、性能调优工具介绍
1.1、静态分析工具 – Analyze
相信 iOS
开发者在 App
进行 Build
或 Archive
时,会产生很多编译警告,这些警告是编译时产生的,静态分析的过程也类似,在 XCode Product
菜单下,点击 Analyze
对 App
进行静态分析。
Analyze
主要分析以下四种问题:
1、逻辑错误:访问空指针或未初始化的变量等;
2、内存管理错误:如内存泄漏;
3、声明错误:从未使用的变量;
4、API调用错误:未包含使用的库和框架。
1.2、内存泄漏分析工具 – Leaks
点击 XCode
的 Product
菜单 Profile
启动 Instruments
,使用 Leaks
开始动态分析。
选择 Leaks
,会自动启动 Leaks
工具和 IOS
模拟器,Leaks
启动后会开始录制,随着对模拟器运行的 App
的操作,可以在 Leaks
中查看内存占用的情况。
注:如果项目使用了 ARC
,随着操作,不断地开启或关闭视图,内存可能持续上升,但这不一定表示存在内存泄漏,ARC
释放的时机是不固定的。
Leaks
顶部分为两栏:All Heap & Anonymous VM
和 Leaks Checks
,All Heap & Anonymous VM
中的曲线代表内存分配和内存泄漏曲线。

点击第二栏 Leaks Checks
展示内存泄漏,进行内存泄漏分析,将光标放置在上图的小红叉上可看到 leak
数量,右下方是leaks
调试的选项:

建议把 Snapshot Interval
间隔时间设置为10秒,勾选 Automatic Snapshotting
,Leaks
会自动进行内存捕捉分析。
在你怀疑有内存泄漏的操作前和操作后,可以点击 Snapshot Now
进行手动捕捉。
Leaked Object
的表格中显示了内存泄漏的类型、数量及内存空间等。
点击具体的某个内存泄漏对象,在右侧 Detail
窗口中会出现导致泄漏可能的位置,其中 黑色头像(现在是蓝色头像)
代表了最可能的位置,具体使用可以参考我的文章 Instruments之Leaks的简单使用。

内存泄漏动态分析技巧:
- 熟练使用
Leaks
后会对内存泄漏判断更准确,在可能导致泄漏的操作里,多使用Snapshot Now
手动捕捉。 - 开始时如果设备性能较好,可以把自动捕捉间隔设置为
5
秒钟。 - 使用
ARC
的项目,一般内存泄漏都是malloc
、自定义结构、资源引起的,多注意这些地方进行分析。
开启ARC后,内存泄漏的原因:
- 开启了ARC并不是就不会存在内存问题,苹果有句名言:
ARC is only for NSObject
。
在iOS
中使用malloc
分配的内存,ARC
是不会处理的,需要自己进行处理。
例子中的CGImageRef
也是一个Image
的指针,ARC
也不会进行处理。
1.3 不合理内存分析工具 – Allocation
关于内存的问题,除了内存泄漏以外,还可能存在内存不合理使用的情况,也会导致 iOS
内存警告。
内存的不合理使用往往比内存泄漏更难发现,内存泄漏可以更多借助于工具的判断,而内存的不合理运用更多需要开发者结合代码、架构来进行分析。
明确说明一下两者的区别:
- 内存泄漏:指内存被分配了,但是程序中已经没有指向该内存的指针,导致该内存无法被释放,一直占用着内存,产生内存泄漏。
- 内存不合理运用:苹果官方称这种情况为
abandoned memory
,也就是存在已分配内存的引用,但实际上程序中并不会使用,比如图片等对象进行了缓存,但是缓存中的对象一直没有被使用。
Xcode
提供的 Instruments
中的 Allocation
工具可以用来帮你了解内存的分配情况,当你的 App
收到内存警告时,首先应该用Allocation
进行内存分析,了解哪些对象占用了太多内存。
1.4 干掉僵尸对象 – Zombies
僵尸对象,也就是我们会遇到的 EXC_BAD_ACCESS
错误,由于内存已经被释放,而这个对象仍旧保留这那个坏地址而导致的。
在 MRC
的开发中,这个错误比较常见,ARC
下面在使用到 C++
的代码也会遇到。
不过这个工具比较简单,遇到这类错误,打开这个位于 Instruments
下的工具,直接就能帮你定位到,这里就不赘述了。
1.5 性能提升工具 – Time Profile
既然是性能调优,那么怎么提升代码的运行效率其实才是我们程序员最直接的诉求,而这个工具可以辅助我们办到这件事。
Time Profiler
分析原理:
它按照固定的时间间隔来跟踪每一个线程的堆栈信息,通过统计比较时间间隔之间的堆栈状态,来推算某个方法执行了多久,并获得一个近似值。它将各个方法消耗的时间统计起来,形成了我们直接定位需要进行优化的代码的好帮手。
选择 Time Profiler
工具开始测试,这时会自动启动模拟器和 Time Profiler
录制。
- 先进行一些
App
的操作,让Time Profiler
收集足够的数据,尤其是你觉得那些有性能瓶颈的地方。 - 是扩展面板,用来跟踪显示堆栈;
- 里面有设置和详情,可以从这里对录制做些配置,
detail
下查看到cpu
运行的时间都消耗在哪里;
通过对应用的操作,可以在详细面板中看到那些最耗时的操作是哪些,并可以逐行展开查看:
图标为黑色头像的就是 Time Profiler
给我们的提示,有可能存在性能瓶颈的地方,可以逐渐向下展开,找到产生的根本原因。
Time Profiler
参数设置

这里边几个选项的含义如下:
-
Separate by Thread
: 每个线程应该分开考虑。只有这样你才能揪出那些大量占用CPU
的”重”线程 -
Invert Call Tree
: 从上倒下跟踪堆栈,这意味着你看到的表中的方法,将已从第0
帧开始取样,这通常你是想要的,只有这样你才能看到CPU
中话费时间最深的方法.也就是说FuncA{FunB{FunC}}
勾选此项后堆栈以C->B-A
把调用层级最深的C
显示在最外面 -
Hide System Libraries
: 勾选此项你会显示你app
的代码,这是非常有用的. 因为通常你只关心cpu
花在自己代码上的时间不是系统上的 -
Flatten Recursion
: 递归函数, 每个堆栈跟踪一个条目 -
Top Functions
: 一个函数花费的时间直接在该函数中的总和,以及在函数调用该函数所花费的时间的总时间。因此,如果函数A
调用B
,那么A
的时间报告在A
花费的时间加上B
花费的时间,这非常真有用,因为它可以让你每次下到调用堆栈时挑最大的时间数字,归零在你最耗时的方法。
上面的参数在实践中合理设置,也没有什么太多技巧,就是通过数据的隐藏、显示让我们更关注于想找到的数据。
2、性能调优之代码优化
2.1 views
设置为不透明 opaque=YES
opaque
这个属性给渲染系统提供了一个如何处理这个 view
的提示。如果设为 YES
, 渲染系统就认为这个view是完全不透明的,这使得渲染系统优化一些渲染过程和提高性能。
如果设置为NO,渲染系统正常地和其它内容组成这个view。默认值是YES。
给你们看个图,你们就知道了,如果这个属性为NO,那么:

注:
-
opaque
英文意思为不透明的
。 - 如果你想详细了解
view
的opaque
属性,具体可以参考我的文章:view的属性Opaque与性能的关系
2.2 持续更新中...
Author
如果你有什么建议,可以关注我的公众号:iOS开发者进阶
,直接留言,留言必回。

网友评论