iOS 性能优化_AsyncDisplayKit 初探

AsyncDisplayKit 是 Facebook 开源的用于保持 iOS 界面流畅的库。

  1. ASDK 的基本原理



    ASDK 认为,阻塞主线程的任务,主要分为以上三大类,文本和布局的计算、渲染、解码、绘制都可以通过各种方式异步执行,但 UIKit 和 CoreAnimation 相关操作必须在主线程执行。ASDK 的主要任务,就是将这些任务从主线程挪走,而挪不走的,就尽量封装优化。

为了达成这一目标,ASDK 尝试对 UIKit 组件进行封装



这是常见的 UIView 和 CALayer 的关系:UIView 持有 Layer 用于显示,View 中的大部分显示属性实际上是从 Layer 映射而来的;Layer 的 delegate 是 UIView,当其属性改变、动画产生时,View 能够得到通知。UIView 和 CALayer 不是线程安全的,并且只能在主线程创建、访问和销毁。

![](http://upload-images.jianshu.io/upload_images/4653622-ace8647c111ee2d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/500)

ASDK 为此创建了 ASDisplayNode 类,包括了常见属性(比如 frame/bounds/alpha/transform/backgroundColor/superNode/subNodes)等,然后它用 UIView->CALayer 的方式,实现了 ASNode->UIView 这样的一个关系。


当不需要响应触摸事件时,ASDisplayNode 可以被设置为 layer backed,即 ASDisplayNode 充当了原来的 View 的功能,节省了更多资源。
与 UIView 和 CALayer 不同,ASDisplayNode 是线程安全的,它可以在后台线程创建和修改。Node 刚创建的时候,并不会在内部新建 UIView 和 CALayer,直到第一次在主线程访问 UIView 和 CALayer 属性时,它才会在内部生成相应对象。当它的属性(frame/transform)改变后,它并不会立即同步到它持有的 View 或者 Layer 上,而是把改变的属性保存到内部的一个中间变量,稍后需要的时候再通过某个机制一次性设置到内部的 View 和 Layer。

  1. ASDK 的图层预合成
    有时候一个 Layer 会包含许多 sub-Layer,而这些 sub-Layer 并不需要响应触摸事件,也不需要进行动画和位置调整。ASDK 为此实现了一个叫做 pre-composing 的技术,可以把这些 sub-layer 合成渲染为一张图片。开发时,ASNode 已经替代了 UIView 和 CALayer;直接使用各种 Node 并设置为 layer backed 后,ASNode 甚至可以使用预合成来避免创建内部的 UIView 和 CALayer。
    通过这种方式,把一个大的层级,通过一个大的绘制方法绘制到一张图上,性能会获得很大提升。CPU 也避免了创建 UIKit 对象的资源消耗,GPU 避免了多张 Texture 合成和渲染的消耗,更少的 bitmap 也意味着更少的内存占用。

  2. ASDK 异步并行开发
    自4S 开始,苹果移动设备都已经是双核 CPU 以上 ,充分利用多核的优势、并发执行任务对保持界面流畅有很大作用。ASDK 把布局计算、文本排版、图片/文本/图形渲染等操作都封装成较小的任务,并利用 GCD 异步并发执行。如果开发者使用了 ASNode 相关的控件,那么这些并发操作会自动在后台进行,无需进行过多配置。

  3. Runloop 任务分发
    Runloop Work Distribution 是 ASDK 一个比较核心的技术。ASDK 的介绍视频和文档中都没有详细介绍,但是网上关于 Runloop 的博客很多,在这里无需赘述。


iOS 的显示系统是由 VSync 信号驱动的,VSync 由硬件时钟生成,每秒发出60次(这个值取决于设备,iPhone 上通常是 59.97 次)。iOS 图形服务收到 VSync 信号后,会通过 IPC 通知的 App 内,App 的 Runloop 在启动后会注册对应的 CFRunloopSource 通过 math_port 传过来的时钟信号通知,随后 Source 的回调会驱动整个 App 的动画与现实。
Core Animation 在 Runloop 中注册了一个 Observer,监听了 BeforeWaiting 和 Exit 事件,这个 Observer 的优先级是 200 0000,低于其他常见的 Observer。当一个触发事件到来时,Runloop 被唤醒,App 中的代码会执行一些操作,比如创建和调整视图层级
设置 UIView 的 frame、修改 CALayer 的透明度、为视图添加一些动画;这些操作最终会被 CALayer 捕获,并通过 CATransaction 提交到一个中间状态去(CATransaction 的文档中有提到这写内容,但并不完整)。当上面的所有操作结束后,Runloop 即将进入休眠或退出时,关注该事件的 Observer 都会得到通知,这时 CA 注册的那个 Observer 就会在回调中把所有的中间状态合并提交到 GPU 去显示;如果此处有动画,CA 会通过 DisplayLink 等机制多次触发相关流程。
ASDK 在此处模拟了 CoreAnimation 的这个机制,所有针对 ASNode 的修改和提交,总有些任务必须放到主线程中去执行的。当出现这种任务的时候,ASNode 会把任务用 ASASyncTransaction(Group)封装并提交到一个全新容器中去。ASDK 也在 Runloop 中注册了一个Observer,监听的事件和CA一样,但是优先级比 CA 要低。在 Runloop 进入休眠前,CA 处理完事件后,ASDK 就会执行该 loop 内提交的所有任务。具体代码见ASAsyncTransactionGroup
通过这种机制,ASDK 可以在合适的机会把同步、异步的操作同步到主线程中去,并且能获得不错的性能。

  1. 其他
    ASDK 中还封装了许多高级的功能,比如滑动列表的预加载、v2.0 添加新的布局模式等。
    ASDK 是一个很庞大的库,它本身并不推荐你将整个 App 全部改为 ASDK 驱动,把最需要提升交互性能的地方用 ASDK 进行优化就足够了。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 175,490评论 5 419
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 74,060评论 2 335
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 124,407评论 0 291
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 47,741评论 0 248
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 56,543评论 3 329
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 43,040评论 1 246
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 34,107评论 3 358
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 32,646评论 0 229
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 36,694评论 1 271
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 32,398评论 2 279
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 33,987评论 1 288
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 30,097评论 3 285
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 35,298评论 3 282
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 27,278评论 0 14
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 28,413评论 1 232
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 38,397评论 2 309
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 38,099评论 2 314

推荐阅读更多精彩内容