几种圆角处理在列表中的性能测试

在平时开发中,圆角处理是一个非常常见的场景,光栅化是一个最简单的优化方法,但是你所使用的方法真的如你所愿的在生效吗?这里对几种比较常用的方法对比一下。

首先按照最常用的几种方式设计了几个case,使用CollectionView来测试性能。Github

几种圆角处理在列表中的性能测试_第1张图片
snapshot.png

1. 纯粹的设置layer属性方式

self.layer.cornerRadius = frame.size.width/2;
self.layer.borderColor = [UIColor blackColor].CGColor;
self.layer.borderWidth = 1;
self.clipsToBounds = YES;

这里不考虑非clipsToBounds的情况,因为大部分场景是需要的,而且非clipsToBounds的话和其他case并不平等。

2. 增加光栅化处理

self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [UIScreen mainScreen].scale;

3. 绘制Image

UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
[[UIColor blackColor] setStroke];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.5, 0.5, size.width - 1, size.height - 1) cornerRadius:size.width/2];
path.lineWidth = 1;
[path stroke];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

4. 绘制Image并且加上缓存

测试

以上case都是在init中就设置好了属性,不会产生reuse的性能问题。为了让效果更加明显,找了一个5s的设备进行测试。

下面是只有一个空的view的结果

几种圆角处理在列表中的性能测试_第2张图片
only_view.png

从结果来看,似乎有点出乎意料,单纯的设置layer属性居然是表现最好的一个,而增加光栅化的表现明显最差,除去可能产生的误差,1和2的结果相差还是有点大。

打开模拟器的Offscreen-Rendered功能,发现1由于没有子视图,所以clipsToBounds属性无效,并不会发生离线渲染,而一旦指定了光栅化,就会强制执行离屏渲染,导致性能急剧下降。

那么我们在视图上加上一个视图

几种圆角处理在列表中的性能测试_第3张图片
with_label.png

结果发生了戏剧性的变化。光栅化的视图直接接近0的帧率,而3和4除了初始化的时间有差别外其他基本符合预期,4高一点可能是用了同一份内存,拷贝到GPU的时候系统做了优化。

那么我们把label不要放在圆角view上

这时候1和2表现一致,应该都产生了离屏渲染。

几种圆角处理在列表中的性能测试_第4张图片
without_subview.png

所以问题来了

我们平时可能用到的光栅化为什么没用了。这要涉及到光栅化cache的策略了,我没有找到详细的官方文档,只找到一段话:

And if you start setting lots of views with shouldRasterize, you're going to overflow the cache and that ends up in a really, really bad situation, ends up being much worse than before because essentially you're rendering every single view that you set with shouldRasterize offscreen and the back on the screen and we just talked about how doing that in every frame can really, really hurt your animation performance.

大量的光栅化导致缓存溢出,所以每次还是需要离屏渲染。

另外,该文章还说

So make sure you don't change anything during your view hierarchy while you have shouldRasterize on, otherwise you ended up rendering offscreen without great performance.

这就是我们平时说的“不能经常变动的视图”,但是注意的是,应该是整个视图树,而且是anything,这样的要求太过于严格。所以为什么很多时候的光栅化会让性能问题更加严重。

HOW

最好的方式当然是绘制圆角并缓存,或者覆盖一张空心圆角的视图。

当你觉得你需要的时候,才开始优化。这才是最好的思路,不要做过早的优化。

你可能感兴趣的:(几种圆角处理在列表中的性能测试)