善恶众相

  • 首页

  • 分类

  • 归档

iOS应用性能调优

发表于 2015-09-09 更新于 2019-08-07 分类于 iOS
从应用启动、绘图和动画动画、内存等角度探究性能优化的注意事项

性能调优工作流程

通过上图我们可以看出性能调试的过程:

  1. 重现性能问题(如:反应慢,动画卡顿等),利用Profile工具或经验查找问题原因
  2. 通过观察提出存在问题的假设,
  3. 反复观察Profile工具表现,确定正确的假设
  4. 根据假设改进程序
  5. 改进之后再次观察应用查看问题是否存在

应用启动

看门狗程序的时限

从某种意义上说,应用启动的性能是给用户的第一印象,所以启动时间越短给用户的第一印象越好,一般很少有人会注意,系统的看门狗程序对你的应用制定了一系列的时限,如果特定场景下应用响应时间超出了这些时限,看门狗程序会直接结束你的应用,当然另外一种情况是用户在启动应用时不想再等下去了,直接手动结束了应用启动。下面列举了系统看门狗规定的场景及时限。

场景 时限
Launch 20s
Resume 10s
Suspend 10s
Quit 6s
Backgournd task 10m

注意:

Xcode在调试的时候会禁掉系统看门狗程序

如何衡量启动时间

输出系统时间

  • 在main()函数中记录系统开始启动的时间
1
2
int main(int argc, char **argv) {
     StartTime = CFAbsoluteTimeGetCurrent();
...
  • 应用启动完成时输出启动所用的时间
1
- (void)applicationDidFinishLaunching:(UIApplication *)app {
     dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"Launched in %f sec", CFAbsoluteTimeGetCurrent() - StartTime);
     });

利用Time Profile确定启动时间

  • 切换到Sample List找到main()函数,即为启动开始的时间,如下图:
  • 找到didFinishLaunchWithOptions,即为启动结束的时间,如图:

应用启动步骤

链接和加载

介绍:

链接加载发生在Time Profiler中的dyld阶段,该阶段library将被映射进相应的内存空间,然后进行绑定和修复,最后进行一些静态变量的初始化。

建议:

  • 由于每一个Objective-C的framework映射进内存都需要时间的,所以避免链接无用的framework
  • 被标记为Optinal的framework需要额外的判断工作,所以不要把所有系统版本都需要的framework标记为Optinal

UIKit初始化

介绍:

该阶段会对与视图相关的内容进行初始化如:Fonts,status bar,user defaults,main nib等

这些内容的初始化是在以下过程中完成的:

1
UIApplicationInitialize
UIApplicationInstantiateSingleton
-[UIApplication _createStatusBarWithRequestedStyle: ...]
-[UIApplication _loadMainNibFileNamed:bundle:]

建议:

  • 尽量减少不必要的控件添加到nib中
  • 偏好设置(User Default)是用于存储属性的,并且它是被一次性反序列化的,所以不要试图在其中存储过大的数据,比如:图片,文件等。

处理application delegate method

介绍:

UIKit会在一下回调中调用你的代码来完成程序的启动

  1. 调用application:willFinishLaunchingWithOptions:
  2. 恢复应用的状态
  3. 调用application:didFinishLaunchingWithOptions:

经过以上步骤应用会完全在你的代码控制之下

建议:

  • 由于application:didFinishLaunchingWithOptions回调的执行也属于应用启动的过程,所以应该尽量避免在该回掉中进行一些费时的操作,如:复杂数据的处理、I/O的操作等。

第一次动画事物

介绍:

由于应用启动准备任务完成之后,最终会将应用的内容呈现在屏幕上,而呈现的方式就是一个视图从小到大的动画,所以这一步的优化就变成了针对动画的优化

针对于动画的优化下一章节我们将详细讲解。

绘图和动画

影响动画性能的因素

根据这篇文章的介绍,动画执行过程中我们能够控制的阶段是下图高亮的阶段:

引起动画性能问题的因素主要有以下两点:

  • 布局
    • 复杂的视图继承关系
    • 懒加载视图
    • 通过访问数据库得到的数据来初始化视图
  • 绘制
    • -drawRect 如非必要,尽量不要重载drawRect方法
    • 字符绘制 如:UILabel控件最终是绘制出来的
    • 图片解码 针对图片视图的动画,commit之前对图片的解码是必不可少的步骤,所以推荐使用png/jpeg格式的图片,苹果对这两种图片的解码做了内部的优化

改善动画性能的关键点

尽量减少设置操作

  • 在进行布局的时候,尽量避免重CPU(如复杂的浮点运算)或阻塞操作
  • 使用内存缓存,将多次用到的属性或对象存储在内存中,静态变量或单例等
  • 确保数据库有合适的索引以供查询
  • 尽可能复用cell或view

减少绘制

  • 只在需要的时候调用-setNeedsDisplay进行重绘
  • 如非必要不要重载-drawRect:
  • 尽量使用-setNeedsDisplayInRect缩小重绘区域
  • 如果不需要交互的话,使用CALayer的属性代替视图的属性

高效的使用image

图像和图层:

  • UIImage是CGImage的轻量级的扩展
  • CALayer的contents属性可以指向CGImage
  • CGImage是以文件或数据形式进行存储的,但最终是以位图的形式加载进内存的

与[UIImage draw…]相比UIImageView做了如下优化:

  • CATrasaction可以从CGImage直接获取位图
  • 允许通过GPU进行混合
  • 内建的位图缓存

一些建议:

  • 保证图片与视图的size相符合
  • 尽量不设置图片的alpha属性,图层混合需要额外消耗性能
  • 只使用PNG或JPEG格式的图片

PNG与JPEG图片格式:

PNG采用的是无损压缩,JPEG采用的经过优化的压缩算法;
PNG存在alpha通道,JPEG没有alpha通道;
JPEG的文件相对较小,JPEG图片解码的时间相对较短

xcode针对PNG的一些优化:

  • 预乘alpha(抗锯齿渲染的一种技术)和字节转换(byte-swap)
  • 禁止一些PNG的混合模式
  • 对一张图片可以进行并行解码,加快解码速度

图像的缓存:

  • 当image被绘制进一个位图上下文时
    • [UIimage imageNamed:]方法会将image缓存进可擦除的内存中
    • [UIImage imageWithContentsOfFile:]则不会对image进行缓存
  • 所有CGImage被赋值给layer的contents属性时,都会被系统缓存起来
  • kCGImageSourceShouldCache
    • 标识image是否会被缓存进解码表(decoded form)中
  • 一般情况下不要试图自己缓存image

-drawsAsynchronously

  • 当layer的该属性被设置为YES的时候,被传递给-drawInContent:方法的CGContent对象会将提交给它的绘图指令进行序列化存储,然后异步的去执行这些绘图操作(也就是说-drawInContent:方法会异步的执行)。这样可以使得layer的绘图操作推迟一会儿执行,不会等到它绘图操作完成之后再往下执行。默认值是NO
视图,层和动画
iOS Copy操作那些坑
  • 文章目录
  • 站点概览
Zrongl

Zrongl

23 日志
3 分类
GitHub E-Mail
  1. 1. 性能调优工作流程
  2. 2. 应用启动
    1. 2.1. 看门狗程序的时限
    2. 2.2. 如何衡量启动时间
    3. 2.3. 输出系统时间
    4. 2.4. 利用Time Profile确定启动时间
    5. 2.5. 应用启动步骤
    6. 2.6. 链接和加载
    7. 2.7. UIKit初始化
    8. 2.8. 处理application delegate method
    9. 2.9. 第一次动画事物
  3. 3. 绘图和动画
    1. 3.1. 影响动画性能的因素
    2. 3.2. 改善动画性能的关键点
    3. 3.3. 尽量减少设置操作
    4. 3.4. 减少绘制
    5. 3.5. 高效的使用image
    6. 3.6. -drawsAsynchronously
© 2019 Zrongl
不争无尤
|
主题 – NexT.Mist v7.3.0
0%