在Ok188bet金宝搏官网Cupid,iPhone用户的30%,有设备,我们认为是动力不足。这使得它非常重要的,我们编写我们的应用程序跨最佳性能所有设备。

我们监测我们的用户通过设备型号保留并有过多次当不良优化功能造成旧设备上的用户有最多低7%的保留。它重申了我们一个应用程序的配合和完成真正重要的!

此外,随着新的iPad的发布与120Hz的显示器,该门槛已经提高到提供超高性能的滚动体验。

本教程

本教程将去深入了解如何使用苹果的时间探查,步行通过与滚动性能问题的困扰实例项目调试成功CPU瓶颈。☠️☠️☠️

我们的目标是,到大功告成的时候,你将有一个更好地了解如何在自己的应用程序发现的缺陷很多。我也将分享我们在这里OkCupid采用一些优化技术。188bet金宝搏官网

请记住下列事项:

  • 优化您的应用程序的做法有时会写简单的或高性能的代码之间的权衡。成功的关键是惊人的平衡。

例如,AsyncDisplayKit /纹理是高性能的布局是一个非常强大的框架,但你知道如何编写目标C ++?你可以解决它,如果你遇到一个搅局者的错误?如果一款iOS升级休息的整合?

增加一个外部的依赖之前,您应该用尽苹果的API中的所有选项。

  • 尽早并经常简介。你赶上一个性能回归越早,就越容易的代码将是重构。

  • 要查看性能问题,你必须轮廓上的实际设备,而不是模拟器。

设备动力不足

188bet金宝搏官网OkCupid目前动力不足的设备列表中包括了iPhone 5系列和iPhone 6+(3X渲染株的CPU)。你会得到最出本教程的,如果你有这些设备方便的一个,但你仍然可以用较新的手机跟着一起。我创建了一个布局,这将使即使最好的设备丢弃帧。

入门

克隆git的回购就设在这里并打开示例项目。在该项目的目标,设定你的团队的“签名”部分。当你运行它的应用已经完全为60fps的滚动优化,你会发现。但是,您可以通过9号线在AppDelegate中设置kIsOptimized =假触发应用程序的性能问题。

AppDelegate中

来吧,做到这一点,然后重新运行该项目。注意到其中的差别在手机上为您滚动?滚动会出现震荡,因为它掉帧试图呈现内容。在Xcode打停。

导航到OKConversationMessageClient线30和替换“表情符号”与“mixedCharacters”就像这样:

客户

你会看到更口吃时,你重新运行该应用程序。

如果你改变“mixedCharacters”到“字母”,你会看到完全平滑滚动甚至上最古老的设备。

重要的教训#1:

考虑到许多不同的场景,当你测试你的应用程序性能。

在示例应用程序,如短一行消息“嘿”,将产生在屏幕上比段长的消息更大量的细胞。这意味着所有这些细胞必须布局在快速连续在主线程上。更糟糕的是比细胞后实例化另一个是多个单元格在屏幕上即将在同一时间。

除了细胞的数量,想想含量的变化是可能的。

让我们看一下文本渲染的例子。你使用带有链接高亮复杂属性文本?如何支持语言,如阿拉伯语,希伯来语和普通话?将您的文本包含表情符号?(大概,因为它是2017年...)。所有这些因素影响的UILabel的绘图性能,TTTAttributedLabel(这是一个很好和高性能的开源框架)和UITextView的。

考虑到这一点,让我们切换OKConversationMessageClient线路30回“表情符号”。但是这一次,而不是运行应用程序,让我们的个人资料,并查明非高性能的代码!

时间探查

时间Profiler是一个非常有用的工具,样品手机的CPU一个每秒一千次。每个样本是一个回溯,这是CPU正在执行什么样的摘要的记录,以及如何到达那里。

然后,它symbolicates回溯并显示多少次的每个符号(方法)发生与“时间”它花了手机的CPU上运行。

之所以说“时间”是加引号是因为这是给你们的毫秒数为实际计算:
(样品中计数符号的发生的)X(样品之间的时间)。

那么也就是说......时间探查未测量方法花费运行时间。相反,它捕获或者长时间运行的方法或快速运行是射击多次的方法。

但不管此限制,探查提供了宝贵的见解在其上的代码行消耗CPU,因此手机的电池也是如此。我强烈建议你看看下面如果你有兴趣在苹果的Time探查器的内部工作深入去这些资源:

时间简档在WWDC 16

时间Profiler用户指南

Facebook上建立了一个工具可在现场配置文件的设备和数据发送到服务器,但它是由你来发送和接收数据,并随后symbolicate它。对于我们而言,苹果的Time Profiler是正是我们想要的。

所以让我们尝试一下!

在Xcode中按住“运行”按钮,并选择个人资料。

探查

Xcode中会立即开始建造和完成时仪器窗口将打开。选择“时间探查器”,点击OK。

仪器

当分析器打开,打红色录音键和应用程序将启动。一经推出,向下滚动,看着时间简档记录数据。已滚动5-10秒后按下停止按钮。

你应该探查看起来是这样的:

时间探查仪

注释:

  1. 这是CPU使用率随时间的曲线图。您可以突出显示图形和刚刚发生在强调时期的痕迹下方将过滤细节部分的部分。您还可以捏放大为更精细的高亮显示。

  2. 顶部拨动你如何看待CPU使用率,这对于缩小问题特别有帮助这三个按钮。

  3. 详细信息部分显示由线程细分的回溯。记住,时间被计算为(样本数)X(样品之间的时间)。

  4. 调用树选项提供了分组和过滤数据的有意义的方式。

  5. 该工艺搜索栏可以过滤对符号或进程名迹。

  6. 最重的堆栈跟踪显示发生的样品中大部分的痕迹。

现在,我们有我们的记录,突出当您通过邮件滚动发生的图的一部分。这将过滤掉启动应用程序,建立视图控制器和动画细胞有关的沉重代价。

看看最重的堆栈跟踪。

你会看到很多的符号,你不认识的,但是当你向下滚动,你会发现[的UILabel drawTextInRect:]... 答对了!正如我们的“字母”和“表情符号”对话的初始交换向我们展示了,该拉的UILabel是极其昂贵的。你可以在这里看到的是,它是占突出显示的结果采样的所有符号的31.6%。注意:您自己的跟踪将会有不同的%数由于字符串值中的消息对象的随机化,和您的iOS版本,设备型号,你如何快速滚动等。

时间探查仪

现在,让出OKMessageCell 79号线的属性串的设置的意见并重新运行时间简档,证明我们已经正确识别的问题。

时间探查仪

如果我们是正确的,[的UILabel drawTextInRect:]应该不再是结果最重的堆栈跟踪。它还将从跟踪中删除大量的噪音,看什么都可以被优化。

经过相同的动作像以前一样......在Xcode中打文件,选择时间探查,命中纪录,当应用程序启动滚动几秒钟的消息,然后点击停止。

好消息![的UILabel drawTextInRect:]不再是最重的堆栈跟踪。相反,我们的...OKMessageCell.layoutCell()现在最重的堆栈跟踪记录突出显示的结果中的所有符号的28.6%出现。

时间探查仪

但是,符号由多个组件组成:

时间探查仪

注意:您可能会看到[的UILabel _intrinsicSizeWithinSize:]作为最重的堆栈,但同样取决于多种因素。在上面的截图中可以看出,在UIImageView的做了很多的工作。这可能是由于我们使用可拉伸的图像的与帽插图或者甚至我们正在申请传入或传出气泡颜色的色调。

超级方便的技巧,通过消除噪音是使用“包括符号”搜索功能。

时间探查仪

它需要猜测私有的API苹果映射到调用您的应用程序功能的一点点,但它不是火箭科学要么!

如果你在“色调”键入时获得这样的:
时间探查仪

如果你在“调整大小”输入你得到这样的:
时间探查仪

虽然并非万无一失,在确定是否设置色调是我们的罪魁祸首,跟踪的51毫秒[UIView的setTintColor]对1个毫秒的痕迹_setContentStetchForImage使我们有信心,试图首先修复的色调。

回顾中的其他节点OKMessageCell.layoutCell()树显示,实例化图像,上浆标签([的UILabel _intrinsicSizeWithinSize:])和创建归属字符串([NSConcreteAttributedString initWithString:属性:])主线程上的所有招致成本。

我们的个人资料的应用最后一次。当它启动,旋转显示屏。注意应用旋转完成前挂几秒钟。

停止Profiler和突出,同时旋转发生的尖峰。您将看到以下内容:
时间探查仪

重要的教训#2:

UICollectionViewDelegate电话sizeForItemAtIndexPath对于一切小区时reloadData或发生旋转时。它需要计算集合视图的内容大小。确保你可以在这个函数,你正在做的少。

另外,还要注意sizeForItemAtIndexPath被称为上旋转的动画块内。这可能会导致意想不到的后果。在我们的例子中,变换称为OKMessageCell.configureBubbleImageView(附:OKMessage)是动画和旋转它完全阻塞主线程。

在上面的截图,如果你双击上[UIView的的setTransform:]它会带你到代码的一部分被采样。请记住,所有的“1598x”告诉我们的是,是,符号突出显示样品中露面的次数。

时间探查仪

业绩修正

所以,现在是不是到了我们解决性能问题的时间。对于那些你沿着示例项目之后,搜索kIsOptimized布尔并注意它是如何禁止或者允许的性能提升的实例。

首先,你可以看到OKConversationAssetFactoryOKConversationSizingFactory该kIsOptimized阻止使用我们的缓存层。

资产厂

另外,还要注意在OKConversationAssetFactory我们同时设置着色颜色和图像本身的改造在视图级别应用它在主线程上,而不是。

资产厂

此外,在OKConversationAssetFactory我们创建的标签尺寸消息的属性串的图像表示,我们将在从进料OKConversationSizingFactory

资产厂

重要的教训#3:

苹果的Safari浏览器的应用程序使用类似的文本渲染技术给我们的属性串为图像的缓存。当用户正在滚动,在屏幕上显示的内容的高速缓存的较低质量的图像。该助手与滚动性能。当用户完成滚动,即缓存图像被换出一个更高的质量,交互式视图。

如果你看一看OKConversationViewController287行,你会看到我们听滚动停下来,换出我们的图像渲染与可点击的文本字段中的代码。

滚动

把它放在一起

所有缓存的变化是巨大的,所有...但他们将在解决我们的性能问题,如果我们不产生在后台线程的原因字符串,图像和大小有效无用。

为了你自己的应用程序,这应该是做了一个API调用返回JSON后,但你更新你的收藏视图的数据源之前。看到OKConversationViewController如何示例应用程序执行缓存线163。

滚动

重要的教训4:

iPhone CPU具有多个核心,但主线程(或与此有关的任何线程)只能在一个时间上的一个核心上执行。如果改为在后台线程同时执行多个任务的工作会快两倍,2核CPU上发生,但CPU%的高一倍。这听起来很糟糕的电池续航时间吧?

其实并非如此!为了让一个CPU完成的工作完全进入低功耗模式的能力,是手机电池的电量比在一段较长的时间在一个核心上执行相同的操作更好。

让我们来谈谈在房间里的大象...

我不使用的视图类自动布局的限制。不要误会我的意思。自动布局的限制在许多方面是惊人的。让我们在优点/缺点:

优点

  • 约束可以计算出高度复杂的布局,其中有一些影响的周围景色的位置的多个视图。

  • 约束可以快速构建在笔尖,不仅让你的类代码干净,但为您提供了一个可视化编辑器查看布局将如何工作。这包括大小类礼节为好。

  • 约束可以与具有内在的尺寸视图类通信,省去您的代码sizeThatFits:逻辑。

  • 约束是易于阅读和你的团队成员的支持。

缺点

  • 在笔尖约束不能被复制到您的应用程序的另一个笔尖。

  • 在笔尖约束是很难跟踪在Git中,如果更改。

  • 约束执行所有固有大小计算(sizeThatFits)在每个池都在屏幕上时,主线程。

  • 约束要求网点,可以大量的代码添加到您的类,而不是仅仅作为出口性能,而且在任何地方你操纵它们。看一眼OKMessageCell你会看到,为了messageLabelImageView的操作开关从messageLabel很容易通过设置一帧.zero,另一个缓存标签框架刚刚完成。

  • 如果约束没有做明确的CPU开销增加计算。例如:

    ✅view.trailing ==不变

    ❌view.trailing <= otherView.leading

笔尖上的一些注意事项具体...

  • 笔尖添加到应用程序的编译时间。
  • 笔尖不能由两家开发商在同一时间的工作没有在Git中造成凌乱的diff。

综上所述

嗯,我希望你学到了一些东西从本教程新!总结要点,要牢记:

  • 测试旧设备上您的应用程序。
  • 时间早,往往简介。
  • 只添加外部依赖作为最后的手段。
  • 当测试应用程序的性能,总是考虑很多不同的方案。
  • 在后台线程缓存以提高性能和电池寿命。
  • UICollectionView sizeThatFits被调用每一个细胞,请确保您的大小的逻辑是最小的,并且尽可能的优化。
  • 约束往往是一个性能瓶颈,如果使用不当。

**188bet金宝搏官网 OkCupid被雇用的iOS!** [点击这里了解更多](https://www.okcupid.com/careers)。