http://www.cocoachina.com/ios/20160105/14870.html

提高 Facebook 应用的性能已经成为 Facebook 持续关注的领域。因为我们相信一个高性能的应用能够传递一种吸引人且令人愉悦的体验。每个 Facebook 应用的用户都必须做的一件事是启动应用(我们特指这个动作为 ”应用启动“)。因此,这是一个很好的优化目标。

稳定的指标

实现最好的性能度量标准和相应的目标,鼓舞我们专注于提升应用的品质,并且我们相信这将会产生很大的影响。度量必须易懂、经得起推敲,并且需要精确地捕捉到将要被优化的体验。对基于性能的度量,我们已经发现在使用应用过程中,最好是使用那些被捕捉到感知的交互。理想情况下,这些度量应该和一个通过基础设施的单一执行通道有一对一的联系。对于应用程序的启动,确定用于衡量的关键位置是一个挑战。这需要采取几次迭代去简化我们的测量和移除边界问题。

应用启动是一个特别不固定的概念,因为现在存在很多种应用启动的方式。应用可以在后台或者前台启动,甚至可以在后台启动,但是在完成初始化之前转换为前台。你可以通过点击一条通知或者通过一个 URL 打开应用。Facebook 应用甚至可以通过其他应用来打开,因为他们需要通过 Facebook 来实现第三方登录。在现实场景中,主要的交互还是最直接的方式:你点击桌面的应用图标,然后跳转启动。因而,我们选择这个作为应用启动的入口。

当启动入口明确之后,我们必须去计算出何时应用启动是完成的。同样地,我们观察用户的使用模式,发现用户喜欢打开应用(首先跳转到新闻摘要),然后等待摘要的加载。我们断定“摘要完成加载”是应用启动一个很好的终点。我们采取了一些微调使得这个终点契合用户的使用情况。我们可以通过重复地观察应用的启动,围绕度量标准来提高应用的性能。

一旦确定了我们认为有代表性的启动入口和终点,我们把启动问题分解成两种类型:

  • 冷启动。指的是当应用还没准备好运行时,我们必须加载和构建整个应用。这包括设置屏幕底部的分栏菜单,确保用户是否被合适地登录,以及处理其他更多的事情。“引导”程序是在applicationDidFinishLaunching:withOptions:方法中开始的。

  • 热启动。指的是应用已经运行但是在后台被挂起(比如用户点击了 home 健),我们只需要知道在何时应用进入后台。在这种情况下,我们的应用通过 applicationWillEnterForeground: 接收到前台的事件,紧接着应用恢复。

我们决定主要优化冷启动,主要有两个原因。
首先,冷启动其实是包括热启动的(冷启动初始化应用并获得摘要;热启动只获得摘要),所以有更多的地方需要优化和微调。
其次,冷启动需要做额外的初始化工作,所以相较而言更慢,导致需要更长的启动等待时间。

优化冷启动体验

我们把冷启动问题分解成三个阶段,进而我们可以有针对性地解决。每个阶段都有一些列变数和挑战。

  • 请求时间:从应用启动到摘要请求离开设备(译者:应该是向服务器发送URL请求算结束时间)的时间。

  • 网络时间:从摘要请求离开设备到服务器响应返回的时间。

  • 响应处理时间:从响应返回到新数据展示在屏幕的时间。

我们直观上认为冷启动性能主要被网络请求和响应处理影响了。这个结论是由于我们假定我们在客户端花的时间比较少,并且我们设法让请求的获取更加快速。然而,当我们用 instrument 去检测时,我们发现数据非常出人意料。它展现出了完全不同的结果,我们发现摘要请求花了大部分时间。另外,响应的处理时间也非常短。因此,我们重新把优化的焦点放在初始化阶段。

Feed请求发送的初始化

所以为什么这个阶段花费了那么多时间呢?很多 iOS 应用并没有这样一个问题——他们在那个阶段并没有很多工作需要做,除了初始化视图控制器和发送网络请求。然而,对于 Facebook 来说,大部分时间被用来开始的时候去设置不同功能块。下面是我们应用中的主要功能块的流程概览。

这看起来好像是很复杂的应用启动设置。但需要重视的是,这些功能块对于 Facebook 应用来说是非常重要的提升,可以提高应用体验,并且使得工程师能够在不同的应用规模下更快地开发。

正如我们所关注的这个流程,我们通过优化独立的部分获得了一些主要的成果。然而,由于未来支持新特性的初始化以及额外提供支持的基础设施,这些成果会慢慢地抵消掉。这使得我们重新考虑如何去解决问题。但我们重新开始,我们认为这个阶段的目标是简单地发送摘要的网络请求。但是为什么摘要请求发出去得这么慢?这是由于很多依赖被添加到摘要的初始化中了。然而,他们并不都是必要的 — 对于摘要请求来说,最少的需要一个有效的验证 token 以及摘要光标(新闻摘要的位置)。因此,我们减少了摘要请求的依赖,让它逐渐地更加接近应用的启动。这允许应用的剩余部分在摘要响应的同时进行初始化。由于这些重构,我们获得了显著的收益。

网络和服务器时间

根据我们在第一阶段的经验,我们继续把这个阶段分解成更小的部分。网络请求/响应看起来像这样:

我们注意到,一旦请求正在排队,发送请求出去之后就有一个时间间隔。这很好解释 — 在冷启动中,网络连接并不是一个开放的、安全的 TCP 连接。一个连接的建立需要三次握手,平均为几百毫秒。当摘要请求第一次发送时,无法避免要花掉这些时间。长远来看,这可以通过缓存 SSL 证书来解决。但是再次强调,我们退回来的目的并不是为了发送 TCP 请求,而是为了从服务器通过任何可能的方式获得请求信息。

我们提出了一个创造性的解决方案 — UDP 启动。本质上,我们在通过 TCP 发送摘要请求时,先发送一个编码过的包含摘要请求的 UDP 包到服务器。这样做的目的是唤醒服务器更早地去获取和缓存数据。当真正的摘要请求通过 TCP 到达时,服务器只需见到地从缓存内容中构造出响应,并发回客户端。这个技术使得我们可以减少几百毫秒的耗时。

当我们持续深入研究服务器端时,我们开始尝试使用 层-取(story-fetching)策略。过去我们已经做了一批摘要请求的 3+7 层。原因很简单:下载次数和被下载的层成正比。因此,把请求分割成两块,允许开始的三层先进来,其余的七个随后进来。通过提升我们的基础设施,我们已经能够升级为 1+1+X 策略,这已经接近于流了。这样就减少了服务器必须处理第一层的时间,并且能够减少下载的时间,使得可以在最快的时间内与用户交互。通过这样的努力,这样我们又减少了几百毫秒的耗时。

Feed响应处理

正如在前面提到的那样,我们以为在启动时会在这里花费大量的时间。但是这个想法被证明是错误的。更加使人好奇的是,我们注意到时间并没有花在处理和加工层上面。时间被花在运行应用服务和竞争资源上面。我们注意到这是我们优化网络和服务器时间的副作用,因为摘要请求返回得太早了。尽管大多数的服务是不重要的。因此,我们开发出一个简单的机制去序列化这些工作直到应用完成启动,并且使用先进先出的方式去执行。这样可以用更少的连接去处理所有层,大大地减少了获得响应和展示在屏幕之间的时间。

总结

很难理解我们在过去几个月走了多远。总之,在一对一的比较中,我们发现我们成功地优化了一秒多的耗时。

优化这个特殊的交互是一个长期的过程,需要建立一个稳定的度量,这个度量必须是易懂的、符合真实世界性能特征,此外要不断地重新思考问题,以提出创新的解决方案。我们希望这可以帮助使用 Facebook 的人有更好的、令人愉悦的用户体验。

你也可以看看 Greg Moeck在 2015 年的演讲

Facebook iOS App如何优化启动时间的更多相关文章

  1. iOS App 性能优化总结

    今天简单总结一些clientapp 优化的方案和方向. 我相信开发一个app大部分团队都能够完毕,可是性能久不一样啦,和我们都写一个冒泡算法一样,我相信每一个人写的冒泡算法都不一样,这些区别就带来了性 ...

  2. iOS app性能优化的那些事

     iPhone上面的应用一直都是以流畅的操作体验而著称,但是由于之前开发人员把注意力更多的放在开发功能上面,比较少去考虑性能的问题,可能这其中涉及到objective-c,c++跟lua,优化起来相对 ...

  3. iOS APP性能优化

    :应用启动时间 应用启动时,只加载启动相关的资源和必须在启动时加载的资源. :本地图片加载方式 本地图片加载常用方法有两种: a. [UIImage imageNamed:@"xx.png& ...

  4. iOS App内存优化之 解决UIImagePickerController的图片对象占用RAM过高问题

    这个坑会在特定的情况下特别明显: 类似朋友圈的添加多张本地选择\拍照 的图片 并在界面上做一个预览功能 由于没有特别的相机\相册需求,则直接使用系统自带的UIImagePickerController ...

  5. 马蜂窝 iOS App 启动治理:回归用户体验

    增长.活跃.留存是移动 App 的常见核心指标,直接反映一款 App 甚至一个互联网公司运行的健康程度和发展动能.启动流程的体验决定了用户的第一印象,在一定程度上影响了用户活跃度和留存率.因此,确保启 ...

  6. android app性能优化大汇总(UI渲染性能优化)

    UI性能测试 性能优化都需要有一个目标,UI的性能优化也是一样.你可能会觉得“我的app加载很快”很重要,但我们还需要了解终端用户的期望,是否可以去量化这些期望呢?我们可以从人机交互心理学的角度来考虑 ...

  7. iOS App稳定性指标及监测

    一个App的稳定性,主要决定于整体的系统架构设计,同时也不可忽略编程的细节,正所谓"千里之堤,溃于蚁穴",一旦考虑不周,看似无关紧要的代码片段可能会带来整体软件系统的崩溃.尤其因为 ...

  8. iOS程序性能优化

    iOS程序性能优化 一.初级 使用ARC进行内存管理 在iOS5发布的ARC,它解决了最常见的内存泄露问题.但是值得注意的是,ARC并不能避免所有的内存泄露.使用ARC之后,工程中可能还会有内存泄露, ...

  9. 20个可以帮你简化iOS app开发流程的工具

    这里推荐20个可以帮你简化iOS app开发流程的工具.很多开发者都使用过这些工具,涉及原型和设计.编程.测试以及最后的营销,基本上涵盖了整个开发过程. 原型和设计 有了一个很好的创意后,你要做的不是 ...

随机推荐

  1. 快速傅里叶变换(FFT)学习

    首先,在写这篇博客之前,我还没有完全学会FFT. 先把会的部分打好,加深一下记忆(也可以说是做笔记吧). 初三了,还不会FFT,要退役喽-- 多项式乘法 点开这篇博客之前,你就应该知道,FFT是用来求 ...

  2. touch滑动事件---简单小案例

    html: <!--导航栏头部--><div class="type_nav"> <ul class="clearfix " v- ...

  3. 处理iphone的 .play() 不能播放问题

    一.添加音乐 <audio id="Jaudio" src="shake.mp3" preload loop="loop" contr ...

  4. Ubuntu添加桌面图标

    下面以添加eclipse图标为例: sudo gedit /usr/share/applications/eclipse.desktop 然后在弹出的文件中输入: [Desktop Entry] Na ...

  5. 011-python列表,元组,字典的用法

    1.列表 1.1 列表截取 list[头下标:尾下标:步长],例如:L[1:10:2] >>> L [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>& ...

  6. Leetcode106. Construct Binary Tree from Inorder and Postorder Traversal中序后续构造二叉树

    根据一棵树的中序遍历与后序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9,15, ...

  7. [Array] 566. Reshape the Matrix

    In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a new o ...

  8. canvas绘制video

    html <video style="position: relative; object-fit: fill;" preload="auto" id=& ...

  9. Hackerrank--Emma and sum of products (FFT)

    题目链接 Emma is really fond of integers and loves playing with them. Her friends were jealous, and to t ...

  10. java窗体swing使用jlabel显示图片

    Icon icon = new ImageIcon("src\\resource\\" + jTFimgName.getText()); jLabColor.setIcon(ico ...