iOS开发系列之性能优化(上)
本篇主要记录一下我对界面优化上的一些探索。关于时间优化的探索将会在中篇里进行介绍。下篇将主要介绍一些耗电优化、安装包瘦身的探索。
### 1、卡顿原理
要了解卡顿原理,需要对帧缓冲区、垂直同步、CPU 和 GPU 几个词进行一下了解,然后综合起来,就可以得到卡顿的答案。本篇我就按照自己的理解来进行描述,如有不当,欢迎指正。
#### 1.1、帧缓冲区
听起来很高大上,其实就是用来存放每一帧画面数据的一个“仓库”,一个仓库只存放一帧画面的数据,iOS 一直是双缓存,就是有两个仓库,存当前帧数据的叫“正式仓库”,存下一帧数据的叫“预备仓库”。
当正式仓库的数据被取走后,两者身份交换,原来的预备仓库转正为正式仓库,原来的正式仓库变成预备仓库。
#### 1.2、垂直同步 (VSync)
就是一个“信号”,通知 app 该开始准备往预备仓库里存放数据了,系统过一会就要来取,这个时间大概是16毫秒。
#### 1.3、CPU (中央处理器)
主要的工作有:正式对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码、图像的绘制。我们可以理解为负责包裹内部的处理工作,简称“打包”。
#### 1.4、GPU (图形处理器)
主要的工作有:将 CPU 计算好的内容进行变换、合成、渲染等处理,然后将渲染结果提交到帧缓冲区。我们可以理解为,对 CPU 给过来的包裹进行分类、排列等操作后,存放到仓库里去,简称“入库”。
#### 1.5、卡顿原理
当收到系统发过来的 VSync “信号”后,CPU 就开始对这一帧画面的数据进行“打包”,然后交给 GPU 进行“入库”操作,存入到“预备仓库”中。
16毫秒后,预备仓库转正,系统开始读取仓库里的数据,如果这个时候,仓库中的数据还没有准备好,那么系统就会大发雷霆,放弃读取仓库中的数据。
那么这个时候,因为系统的宁缺毋滥,导致了显示器上显示的还是上一帧画面,就造成了卡顿的效果。
### 2、性能优化
作为软件开发工程师的我们,既不能延长16毫秒的处理时间,也不能改变系统的脾气,那我们能做的就是尽量在这个时间内完成数据的准备。要么“打包”快一点,要么“入库”快一点,也就是针对 CPU 和 GPU 的工作进行优化,这就是性能优化的工作了。
#### 2.1、CPU 工作之正式对象的创建和销毁
- UITableViewCell 和 UICollectionViewCell 的复用,可以减少 cell 的创建操作;
- 尽量使用轻量级的对象,可以减少对象的创建时间,比如在不需要事件处理的场景里,使用CALayer 比 UIView 会更加合适;
- 表情键盘使用 UICollectionViewCell 代替 UIButton,可以减少对象的创建操作;
- 对象不涉及UI操作,放到后台线程创建;
- 性能敏感的界面,storyborad的资源消耗>代码创建;
- 推迟对象创建的时间,对象放到多个任务中,比如懒加载;
#### 2.2、CPU 工作之对象属性的调整
- UIView 有一个 CALyer 的属性,UIView 负责事件的处理,CALyer 负责图层的绘制和显示。需要注意的是,CALyer本身是没有属性的,所以当改变 UIView 的显示相关的属性如 frame、bounds 和 transform 的时候,会消耗较多的资源,所以减少对这些属性的一些不必要修改,能减小 CPU 的压力;
#### 2.3、CPU 工作之布局计算
- UITableViewCell 高度提前计算并存储,要用的时候直接读取;
- frame 计算好,较少不必要的修改;
- Autolayout会比直接设置frame消耗更多的CPU资源;
#### 2.4、CPU 工作之文本的计算和排版
- 普通文本可以在子线程用 [NSAttributedString boundingRectWithSize:options:context:] 来计算文本宽高,用 -[NSAttributedString drawWithRect:options:context:] 来绘制文本;
- CoreText 对象占用内存较少,当显示大量文本时,可以用 CoreText 对文本异步绘制;
#### 2.5、CPU 工作之图片的格式转换和解码
- 在后台线程先把图片绘制到 CGBitmapContext 中,然后从 Bitmap 直接创建图片;
#### 2.6、CPU 工作之图像的绘制
- UITableViewCell 滑动减速的时候才加载图片,可以参考这个[demo](https://github.com/johnil/VVeboTableViewDemo);
- 加载图片时,imageNamed 方法默认加载图片成功后会内存中缓存图片,下次读取会很快;imageWithContentsOfFile 方法不会缓存图片,大图片可以使用该方法;
#### 2.7、GPU 工作之渲染
- 尽量不要让图片和视图的大小超过 GPU 纹理尺寸上限:4096×4096,不然图片还需要经过 CPU 的处理;
- 尽量减少视图数量和层次,并设置视图为不透明,UIView 的不透明属性 (opaque) 默认为 YES,一般设置背景颜色即可;CALayer 的不透明属性 (opaque) 默认为 NO,需要设置为 YES;
- CALayer 的 border、圆角、阴影、遮罩,通常会触发离屏渲染,尽量少用,圆角属性可以使用 CoreGraphics 绘制或使用圆角图片代替,关于离屏渲染的知识,具体可以参考这篇文章:[iOS 图形性能优化](http://www.cocoachina.com/cms/wap.php?action=article&id=25543);
- 图片的 size 最好刚好跟 UIImageView 的 size 保持一致,这涉及到像素对齐的知识,也可以在上面这篇文章中详细了解;
最后郑重声明,本篇里只是记录一下我的个人理解和代码实践,资料大量参考了这篇文章:[iOS 保持界面流畅的技巧](https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/),作者是写出了 YYKit 框架的大佬,想要深入学习的朋友请移步。
本篇的界面优化就记录到这里,后面会持续更新,欢迎指正。
iOS开发系列之性能优化(上)的更多相关文章
- Android开发系列之性能优化
一直想整理一篇关于Android性能优化的博客,正好今天借鉴一些书籍资料,总结一下自己对于这块的一些认识.相信大家都听说过16ms的原则,即每两个画面之间的绘制时间间隔不能超过16ms,否则人眼能够感 ...
- iOS开发那些事--性能优化–内存泄露问题的解决(转)
内存泄漏问题的解决 内存泄漏(Memory Leaks)是当一个对象或变量在使用完成后没有释放掉,这个对象一直占有着这块内存,直到应用停止.如果这种对象过多内存就会耗尽,其它的应用就无法运行.这个问题 ...
- iOS开发系列--Swift进阶
概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...
- iOS开发系列--通知与消息机制
概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...
- iOS开发系列--让你的应用“动”起来
--iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...
- iOS开发系列--让你的应用“动”起来
--iOS核心动画 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建 ...
- IOS开发系列 --- 核心动画
原始地址:http://www.cnblogs.com/kenshincui/p/3972100.html 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...
- iOS开发系列--让你的应用“动”起来【转载】
概览 原文链接:http://www.cnblogs.com/kenshincui/p/3972100.html 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥i ...
- iOS开发系列--通知与消息机制--转
来自:http://www.cocoachina.com/ios/20150318/11364.html 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户 ...
随机推荐
- Akka边学边写(1)-- Hello, World!
Akka Akka是什么呢?直接引用Akka站点上面的描写叙述吧: Akka is a toolkit and runtime for building highly concurrent, dist ...
- OpenCV中基于Haar特征和级联分类器的人脸检测
使用机器学习的方法进行人脸检测的第一步需要训练人脸分类器,这是一个耗时耗力的过程,需要收集大量的正负样本,并且样本质量的好坏对结果影响巨大,如果样本没有处理好,再优秀的机器学习分类算法都是零. 今年3 ...
- mysql 加入柱更改列删除列
MySQL 加入列,改动列,删除列 ALTER TABLE:加入,改动,删除表的列,约束等表的定义. 查看列:desc 表名; 改动表名:alter table t_book rename to bb ...
- IME输入法编程心得
原文:IME输入法编程心得 posted @ 2012-11-30 00:42 from [FreedomShe] 自然语言处理的输入法作业成品没有做出来,但不想再在蛋疼的Win32上面耗费时间了,整 ...
- 微信小程序之登录页实例
项目效果图: 目录结构: login.wxml: <view class="container"> <view class="login-icon&qu ...
- JScript读取XML文件
作者:朱金灿 来源:http://blog.csdn.net/clever101 JScript读取XML文件需要考虑msxml组件的多个版本,稳妥的做法是将所有版本都列出来. xml文件的内容如下: ...
- XF 标签和文本控件
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http:/ ...
- Win10《芒果TV》更新v3.8.0初夏版:全新视觉体验,即刻分享视频
历时半年多昼夜,千呼万唤始出来,Win10版<芒果TV>全平台同步更新初夏版v3.8.0,统一视觉体验,完善分享投屏,进一步提升使用体验. Win10版<芒果TV>V3.8.0 ...
- 通过Chrome扩展来批量复制知乎好友
1.初始化文件 Chrome 官方扩展教程地址 新建一个文件夹 zhi-follow 下图中 1 部分为 默认的图标3种尺寸 会显示在 Chrome 中 2. 定义按钮样式 页面上会有 ...
- 微信小程序把玩(一)Hello WeApp
原文:微信小程序把玩(一)Hello WeApp 本篇默认已经成功安装微信小程序工具 新建项目 AppID查看公众开发平台设置查看(https://mp.weixin.qq.com) 项目名称随意填写 ...