《iOS三问》 -- iOS UI显示的原理及优化策略(中) -- iOS UI优化工具

工欲善其事,必先利其器。在进一步对UI优化进行探索之前,我们有必要一起先学习下在iOS性能优化中常用到的一些工具。有了上一章iOS UI显示基础的学习,我们应该可以理解这些工具的用途。本章主要也是以了解为主,在下章中,我们会深入到具体的问题,运用我们学到的知识与工具具体地解决之,真正达到学有所获。

1 iOS UI优化原则

1.1 使用真机测试,使用发布配置调试

优化首先的原则就是:当你开始做一些性能方面的工作时,一定要在真机上测试,而不是模拟器。模拟器虽然是加快开发效率的一把利器,但它不能提供准确的真机性能参数。模拟器运行在你的Mac上,然而Mac上的CPU往往比iOS设备要快。而且,Mac上的GPU和iOS设备的完全不一样,模拟器不得已要在软件层面(CPU)模拟设备的GPU,这意味着GPU相关的操作在模拟器上运行的更慢,尤其是使用 CAEAGLLayer 来写一些OpenGL的代码时候。

这就是说在模拟器上的测试出的性能会高度失真。如果动画在模拟器上运行流畅,可能在真机上十分糟糕。如果在模拟器上运行的很卡,也可能在真机上很平滑。你无法确定。

另一件重要的事情就是性能测试一定要用发布配置,而不是调试模式。因为当用发布环境打包的时候,编译器会引入一系列提高性能的优化,例如去掉调试符号或者移除并重新组织代码。你应该只关心发布性能,那才是你需要测试的点。

最后,最好在你支持的设备中使用性能最差的设备上测试,因为一般老的机子性能会相对弱点,如果老的机子都没问题,一般新的机子上效果就只会更好。

2 Xcode集成Debug工具

2.1 Debug Navigator

Xcode自身已经集成有非常牛逼的调试工具了,在观察一般性能问题时,我们甚至都不需要使用instruments。在xCode中调试运行(真机或模拟器),选中左栏中的debug项,就可以看到集成的调试工具。

xCode debug栏

如图所示,在我当前使用的xCode 9.3版本中,可以在debug栏中查看CPU及内存还有磁盘IO等情况了(9.3新增了用电监测功能)。点击右上角,还可以展示一些更牛X的工具,如下:

xCode 更多dump信息

在这里可以查看一些dump信息,比如当前app的view层级(出现UI问题时特别有用),还有内存分配信息,这里特别展示一下:

查看内存分配信息

在这个调试页面,你可以看当前app内存的分配情况,粒度是细化到对象的。可以看某个类有多少个对象实例,以及他们之间的持有关系,这样一眼就看出有没有循环引用了。

2.2 View Debuging

在工具栏的Debug选项中,有许多调试工具可以使用,其中的View Debuging对UI调试比较重要。

View Debuging

我们可以从图中看出这些工具,其中上层的screenShot(截图),show view framw(以view加边框)也是较常用的工具,对于界面的布局比较有用。后面的Rendering则是UI性能调试重要工具,这里着重介绍下:

2.2.1 Color Blended Layers

混合图层,名如其意,回想下我们上一篇iOS UI显示基础中关于GPU图像合成所学到的内容,需要合成的图层超多,GPU的工作就越重。用了这个工具,会使用绿到红的高亮来表示混合的程序,越红表示越多合成,性能自然越差。好好复习下上章的内容,将viewlayeropaque属性设为YES, 去掉视图的透明度及透明背景就可以很好地优化这个点了。

在我的iOSOneDemo中的示例UI优化-优化工具中,我们打开Color Blended Layers,会看到如下这样,因为Label是透明的,会和底层的图层发生颜色合成,所以这里会显示成红色。

混合图层示例

优化方法,我们只要有问题的视图设置为非透明就可以了,比如上例中列表中的Label这样设置:

1
2
cell.textLabel.clipsToBounds = YES;
cell.textLabel.backgroundColor = [UIColor whiteColor];

你甚至可以不需要修改它的opaque属性,这个不透明结论会自动帮你做出(当背景色非透明时)。如果你下载了我的demo的话会发现原来红色的区域不见了。

2.2.2 Color Offscreen-Rendered Yellow (离屏渲染检测器)

这个选项会把那些离屏渲染的图层显示为黄色。黄色越多,性能越差。这些显示为黄色的图层很可能需要用 shadowPath 或者 shouldRasterize 来优化(离屏渲染问题请看下一章UI优化场景-离屏渲染)。

在View Debuging示例小节我们会用实例说明。

2.2.3 Color Hits Green and Misses Red

UIView.layer.shouldRasterize = YES 时,耗时的图片绘制会被缓存,并当做一个简单的扁平图片来呈现(下一章UI优化场景-离屏渲染)。这时候,如果页面的其他区块(比如 UITableViewCell 的复用)使用缓存直接命中,就显示绿色,反之,如果不命中,这时就显示红色。红色越多,性能越差

同样,在View Debuging示例小节我们会用实例说明。

2.2.4 Color Copied images

对于 GPU 不支持的色彩格式的图片只能由 CPU 来处理,把这样的图片标为蓝色。蓝色越多,性能越差。因为,我们不希望在滚动视图的时候,由 CPU 来处理图片,这样可能会对主线程造成阻塞。

2.2.5 Color Misaligned Images

这个选项检查了图片是否被缩放,以及像素是否对齐。把图片放进了与其大小不一致的imageView中会导致缩放.而布局定位不对的view会因为像素对不齐导致紫色,而像素对齐比较常见是自行进行等比缩放时结果没有取整,导致x/y坐标没对齐。 被缩放的图片会被标记为黄色,像素不对齐则会标注为紫色。黄色、紫色越多,性能越差

2.2.6 Color OpenGL Fast Path Blue

这个选项会把任何直接使用 OpenGL 绘制的图层显示为蓝色。蓝色越多,性能越好。如果仅仅使用 UIKit 或者 Core Animation 的 API,那么不会有任何效果。如果使用 GLKView 或者 CAEAGLLayer,那如果不显示蓝色块的话就意味着你正在强制 CPU 渲染额外的纹理,而不是绘制到屏幕。

2.2.7 Flash Updated Regions

这个选项会把重绘的内容显示为黄色。不该出现的黄色越多,性能越差。通常我们希望只是更新的部分被标记完黄色。

3 Instruments

在 Xcode 的 Product-profile 中打开 Instruments.

Instruments

所有工具的应用都是点左上角的录制键开始录制,然后instruments会启动应用,这时你的app就在监控中了,你对App的监控数据如CPU占用率、内存使用情况、界面帧率FPS等都会被相应的工具记录下来。 Instruments的使用就是这样一个录制加分析的过程,虽然使用简单并不复杂,但是功能却非常强大。下面我们来看下在UI性能分析上主要的工具。

3.1 Time Profiler

时间分析器工具的主要作用是用来检测CPU的使用情况。它可以告诉我们程序中的哪个方法正在消耗大量的CPU时间。使用Time profiler可以检测出在程序运行过程中各方法消耗的CPU时间,其中定位到函数的功能是非常有用的。

3.2 Core Animation FPS

Core Animation FPS主要用于观察界面的FPS帧率。

4 View Debuging示例

示例代码具体请看我的iOSOneDemo中的示例UI优化-优化工具。运行界面如下:

ios-ui-advance-blend

4.1 使用 instruments 看页面流畅度与资源占用情况

我们分析问题时如果有明显的卡顿,那么一下子就说明问题了,但是如果不太明显,一开始最好还是先用instruments来看看页面的CPU占用率及FPS帧率。如果CPU占用率高,说明当前肯定做了些耗时计算,这时可以看看是否可以优化下算法或是把计算放到后台队列里去做。如果FPS帧掉得很厉害,就要再进一步分析看是CPU计算量大,还是GPU压力大了。

具体到这个实例,我们先分析下FPS,发现在滑动列表时,帧率平均在20左右,此时CPU占用率不高,见下图中CPU Usage那一项,而GPU利用率高达80%(我用红框框着的).

这样,我们就可以把问题定位在GPU渲染上了。

4.2 Color Blended Layers

我们使用第一节中说的Debug工具Color Blended Layers,看到界面中的透明合成也就是红色部分可以优化。

混合图层示例

  • 分析与解决

因为Lagel是透明背景的,我们可以将之去掉,代码修改:

1
2
cell.textLabel.clipsToBounds = YES;
cell.textLabel.backgroundColor = [UIColor whiteColor];

点击优化控制中的”透明层叠优化”按钮,可以发现,红色的提示区域不见了。

4.3 离屏渲染优化

优化了blend layer后,发现FPS并没有明显的提升,现在我们怀疑还有可能是列表的图片和Labe使用了阴影,造成了离屏渲染了。

我们使用Debug工具Color Offscreen-Rendered Yellow,发现列表项是深黄,说明问题真的存在。

与是我们把阴影的代码去掉,深黄色的内容不见了,FPS也上去了,GPU占用率下降,说明问题真的得到解决。

但是如果我们还是在使用阴影效果呢?参照UI优化场景-离屏渲染所说的使用 shouldRasterize 优化之

使用shouldRasterize优化离屏渲染
1
2
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

使用Color Hits Green and Misses Red,可以看到只有cell刚要绘制时出现红色,问题得到了优雅解决!

这里可以通过界面上方的“优化控制”显示效果就行,具体关于离屏渲染的解释和光栅化解决的原理,请下一章UI优化场景-离屏渲染我们将学习之。

5 引用

坚持原创技术分享,您的支持将鼓励我继续创作!