性能优化守则
1.(重点)提早优化是万恶之源, 不要在项目初期就想着如何优化性能.毕竟软件开发的第一需求是实现,做到之后再谈做好.事实上,,我在debug模式下,打开了微信和支付宝发现也有效率优化的空间,但是人家并不掉帧,所以没有必要如此极致的性能.
- 性能优化和瞎搞只一墙之隔,性能够用即为王道.
- FPS在50-60,勉强可以忍受,设计师的像素眼可能会有所察觉,大多是人不会注意到.
- FPS在45以下,一定要进行优化,这时页面会有明显的卡顿
- 性能优化要找寻关键的瓶颈点,也叫做奇点.犹如一条管道里最细的部分,卡住了所有的资源.只要释放最阻碍性能的部分,就能使得性能大幅度提升.
- 科学的测量性能, 而不是猜测.FPS测量使用CADisplayLink.将加入runloop后,每次屏幕刷新的时候会调用selector,根据调用的时间,算出对应的刷新率.好用的成型的工具: swift-YWFPSLabel, 或者YYKit的组件,已经有人将其单独抽出来OC-YYFPSLabel
- 在真机上测量,不要在模拟器上.不同机型的CPU,对应的处理性能也不一样.Mac的处理器更是吊打多数手机.尽量保证较老的机型流畅运行.代码写的再烂,当年的旗舰CPU也很难出现卡顿
CPU 和GPU
关于绘图和动画有两种处理方式CPU(中央处理器)和GPU(图形处理器),CPU的工作都在软件层面,而GPU的在硬件层面。
总的来说,可以使用CPU做任何事情,但是对于图像的处理,通常GPU会更快,因为GPU使用图像对高度并行浮点运算做了优化,所以,我们想尽可能的把屏幕渲染的工作交给硬件去处理,而问题在于GPU并没有无限制处理的性能,一旦资源用尽,即使CPU并没有完全占用,GPU性能还是会下降。
所以,目前大多的性能优化都是关于智能利用GPU和CPU,平衡它们之间工作负载。
CPU和GPU在硬件架构上导致计算能个偏向不同,详情见下图.简单理解可以为: CPU做高等计算的能力强(单核运算能力),对于cache的依赖较高. GPU并发数较高(单核不强,胜在核心数多),对于cache无太多依赖.而图像处理又是一个苦差事,所以GPU比较强.例图:
架构示例
Color Blended Layers - 检测图层绘制对于性能的影响
设置前图层混合度越高,则颜色会从绿色->红色,越来越深.
当GPU在渲染的时候, 由于其每次(单次帧数)所绘制的像素有限,所以当要反复绘制同一个图层的时候就会出现掉帧现象,防止过度绘制是优化FPS的关键.
影响混合度的因素:
- 控件用了透明色, 或者opaque属性设置了YES(默认为NO)
- UIImageView控件较为特殊,即便其背景色不透明,其图片的alpha通道是透明的,其计算复杂度也会比较非常高.所以在控件优化到黔驴技穷的时候麻烦一下设计师吧
当图层被遮挡的时候, GPU会放弃渲染,但是计算渲染范围也是非常耗费资源的,相较于非透明色的渲染,透明色的渲染要复杂很多.所以 Color Blended Layers 中颜色越深,则耗费的渲染资源越多,优化的关键就是在减少这个渲染的复杂度
- 当UILabel的内容显示中文时,其文字的size会大于lab的高度,外围会有一圈看不见的阴影.设置:
layer.masksToBounds = YES
则会降低渲染的复杂度
设置后
Color Hits Green and Misses Red - 光栅化缓存图层情况,命中绿色,未命中红色
此项是为了检测 layer.shouldRasterize
属性,当此属性为Yes的时候,渲染的图层会被缓存,
如果位图发生了改变,缓存失效后,便会丢弃此修改,然后重新生成.
开启后红色表示需要重新渲染,绿色表示缓存成功.
通常,第一次进入查看其应该是红色尚未缓存,然后当再次查看理应为绿色缓存成功,如果依旧为红色,表示光栅化失效.失效的原因可能多种多样,但核心是: 位图发生了改变
光栅化的好处是,以空间换取时间,但是APP的内存消耗同样很关键,虽然iOS的内存管理比较优秀,但有代价的优化,有的时候可能会帮了倒忙.
Color Copied Image - 检测图片格式
这项是检测图片是否为正确的格式,通常情况下,手机要显示一张图片,需要将图片转化成像素进而进行显示.如果图片格式不达标,GPU无法处理,会转而给CPU处理.CPU被强制生成了一些图片,然后发送到渲染服务器,而不是简单的指向原始图片的的指针。我们不希望在滚动视图的时候,CPU实时来进行处理,因为有可能会阻塞主线程。
若是GPU不支持的图片, 其将会被标记为青色
Color Misaligned Image - 检测图片是否对齐的问题
这里会高亮那些被缩放或者拉伸以及没有正确对齐到像素边界的图片,即图片Size和imageView中的Size不匹配,会使图过程片缩放,而缩放会占用CPU,所以在写代码的时候保证图片的大小匹配好imageView
被放缩的图片会被标记为黄色,像素不对齐则会标注为紫色。黄色、紫色越多,性能越差。
Color Offscreen- Rendered Yellow - 检测离屏渲染
这个选项会把那些离屏渲染的图层显示为黄色。黄色越多,性能越差。
通常离屏渲染的触发条件:
- 遮罩处理不当,
layer.maskToBounds
- 阴影效果
view.shadow
- 光栅化
layer.shouldRastarize
- edge antialiasing(抗锯齿)
- group opacity(不透明)
- 复杂形状设置圆角等
- 渐变
栅格化可以设置屏幕分辨率来优化性能:
layer.drawsAsynchronously
layer.shouldRasterize
layer.rasterizationScale, 设置对应的渲染大小
drawsAsynchronously该属性适用于图层内容需要反复重绘的情况,此时设成true可能会改善性能,比如需要反复绘制大量粒子的粒子发射器的图层。
指定阴影的路径,可以防止离屏渲染, layer.shadowPath
如果没有手动指定,Core Animation会去自动计算,这就会触发离屏渲染。如果人为指定了阴影路径,就可以免去计算
圆角性能优化,可以启用光栅化操作将其存储起来(离屏渲染但是次数少),或者用贝塞尔曲线,CoreGraphics等方式画出圆形图片,参考我的其他blog: imageView圆角设置
iOS 9.0 之前UIimageView跟UIButton设置圆角都会触发离屏渲染
iOS 9.0 之后UIButton设置圆角会触发离屏渲染,而UIImageView里png图片设置圆角不会触发离屏渲染了,如果设置其他阴影效果之类的还是会触发离屏渲染的。
Color Immediately - 立即调用更新
通常 Core Animation Instruments 以每毫秒 10 次的频率更新图层调试颜色。对某些效果来说,这显然太慢了。这个选项就可以用来设置每帧都更新(可能会影响到渲染性能,而且会导致帧率测量不准,所以不要一直都设置它)。
固定在需要的时候点选此选项,查看更准确的图层帧数
Color Compositing Fast-Path Blue - 查看影像合成情况
这个选项会把任何直接使用 OpenGL 绘制的图层显示为蓝色。蓝色越多,性能越好。如果仅仅使用 UIKit 或者 Core Animation 的 API,那么不会有任何效果。如果使用 GLKView 或者 CAEAGLLayer,那如果不显示蓝色块的话就意味着你正在强制 CPU 渲染额外的纹理,而不是绘制到屏幕。
Flash Updated Regions - 查看重绘区域
这个选项会把重绘的内容显示为黄色。也就是软件层面使用Core Graphics 绘制的图层。不该出现的黄色越多,性能越差。通常我们希望只是更新的部分被标记完黄色。
网友评论