参考:
friends-dont-let-friends-render-offscreen
ios-rendering-the-ui
the-shouldrasterize-property-of-a-calayer
Core Animation文档摘抄
when-does-a-view-or-layer-require-offscreen-rendering
http://www.apokrupto.com/blog-1/2016/7/16/qd2osqnhgywx23tqm6qcpwgouufpls
最近看深度学习模型YOLO-v2时,作者为了提高模型的精度,列出了一个模型优化的trick列表,一条一条的去进行优化对比,受这个事情启发,我们在做应用优化时,把知道的trick都列出来,一条一条的去优化,相信也能收获很好的效果。
Core Animation文档中,给出了一些性能优化的建议,同时结合上面的文章。
1、不透明度Opaque设置为YES
Core Animation建议我们将图层的Opaque设置为YES,该属性告诉Core Animation,渲染时不要考虑透明度通道,但是对于使用layer.content设置的图片本身带有的透明通道该属性不会生效。
2、阴影显式的设置Path
Core Animation要求我们给阴影显示的设置shadowPath,以免Core Animation需要进行额外计算。上面friends-dont-let-friends-render-offscreen文章提到,除去这个方法之外,也可以通过使用一张可拉伸的图片来做阴影。
3、不应该使用cornerRadius,maskToBounds,圆角使用图片遮罩,或者Core Graphics绘制,相比来说建议使用图片遮罩
列表中应禁止使用cornerRadius。我们可以通过一张镂空的图片,覆盖在原图上来实现圆角。上面friends-dont-let-friends-render-offscreen文章提到使用UIBezierPath生成圆角。
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
imageView.image = [UIImage imageNamed:@"willwang"];
//开始对imageView进行画图
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 0.0);
//使用贝塞尔曲线画出一个圆形图
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.frame.size.width] addClip];
[imageView drawRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
//结束画图
UIGraphicsEndImageContext();
[self.view addSubview:imageView];
4、性能有问题时使用异步绘制
layer-based渲染比view-based渲染效率更高,应尽量使用layer-based渲染
另外,drawRect方法和drawLayer:Context:方法本身是同步执行,如果你的绘制造成了卡顿,可以设置drawsAsynchrously属性进行异步绘制,但是要保证线程安全。
5、宽度和高度使用整型
Core Animation建议我们设置为Integer。
6、CAShapeLayer的path过于复杂时应当切分
Core Animation建议我们如果path过于复杂,应考虑对其进行分割
7、使用layer.content共用一张资源,避免拷贝
如果有多个地方需要共用图片,使用layer.content直接赋值,可以避免创建多个副本
引自 friends-dont-let-friends-render-offscreen
So What Exactly is Offscreen Rendering?
This concept is one of the more confusing ideas when considering performance on iOS, so I'll do my best to try to help clear up some of that confusion.
On the CPU: Offscreen rendering, or offscreen drawing can just mean what happens when you need to draw a bitmap in memory using software instead of rendering directly to the screen.
For example, writing your own draw method with Core Graphics means your rendering will technically be done in software (offscreen) as opposed to being hardware accelerated like it is when you use a normal CALayer. This is why manually rendering a UIImagewith a CGContext is slower than just assigning the image to a UIImageView.
This type of offscreen rendering can be advantageous at times but should be undertaken only alongside careful testing and measurement.
On the GPU: There's a very specific type of offscreen rendering that can occur when you ask a CALayer to draw something, but haven't given it enough information.
This means that when the Render Server goes to render your layer hierarchy it will get to a layer subtree that it doesn't fully know how to render yet.
This forces it to stall and switch contexts from its normal "onscreen" rendering to "offscreen" rendering in order to fully figure out how to draw what it needs to. Once its done, it can switch back to onscreen drawing and proceed as normal.
The real damage is done by the two context switches! These can really add up if you have many views being animated that force this kind of GPU stall.
This is what the Core Animation Instrument is trying to show us when it colors layers yellow.
There's a few common scenarios where this will happen and pretty straightforward fixes for each.
网友评论