iOS显示性能优化过程讲解

点我跳转原文地址

logo.png

卡顿的原理

iOS系统界面滑动流畅性的保持主要是依靠CPU和GPU两大处理硬件间通力合作的结果,一个视图的显示需要先经过CPU创建、布局计算、对图片解码、文本绘制,然后CPU将计算的结果交给GPU,GPU可能需要对图形进行变换、合成、渲染,GPU然后将渲染的结果提交到帧缓冲区等待下一次的垂直同步信号(V-Sync)到来显示到显示器上,如果在一个V-Sync间隔内CPU或者GPU由于过高的利用率都可能导致数据的不及时提交,那么那一帧数据就会被丢弃,等待下一次的V-Sync再显示,这也就是通常能感受到的界面卡顿现象,也就是掉帧。

优化过程

所以当出现卡顿现象时主要去分析此刻CPU和GPU的利用率,当出现较高的CPU利用率时应及时去分析代码执行的效率,或者用Time Profier去分析导致较高占用率的代码,更多详细的关于优化CPU的情况本文不做详细分析。
而对于GPU资源消耗的优化本文将通过一个Demo优化过程来讲解优化的步骤,你可以在这里GitHub下载源码,Demo是有2个tab组成的,before是优化前视图,after是优化后的,你可以通过对比学习体会其中的差异。
下载运行demo, 打开Xcode的调试选项,在菜单栏-Debug-View Debugging-Rendering可以找到,运行APP(真机)勾选相关的菜单选项即可
Rendering.png

1.视图混合(Blending)

app中显示的效果往往是多个视图重合叠加的效果,而在计算视图重合显示颜色的时候就需要考虑透明的影响,当顶部视图出现透明的情况时,颜色的计算就需要考虑其透明度,这样无疑增加了计算成本,消耗GPU资源,所以应尽量避免过多的透明视图数量。
对于UIImageView而言,如果图片本身是带有透明通道的同样会导致Blending,所以应该尽量避免使用带有透明度的图片。
对于文本UILable, 如果不设置背景颜色,同样会出现Blending,所以需要设置UILabel的背景颜色,对于显示中文的UILabel, 除了设置背景颜色外还需要设置masksToBounds属性,因为中文时UILable会多了一个sublayer。
勾选Rendering中的第一个选项Color Blended Layers,此选项就是用于检测哪些视图出现了Blending,出现Blending的地方会用红色标记出来,运行demo可以出现下图所示情况:
Blending.png

可以看到,before tab下的控制器视图无论是图片还是文本都被标红,表示出现了Blending,对于图片我们可以在Assets里面找到对应的图片,然后查看简介就可以查看图片是否有Alpha通道,会看到图片都具有Alpha通道,也就回导致Blending
Alpha通道.png
对于这种情况,可以让UI切图时关闭此Alpha通道,也可以直接用mac自带的图片软件打开图片,然后导出图片关闭Alpha通道。所以我们需要将所有有Alpha的图片都处理一遍,尽量不要使用带有透明度的图片。
对于UILabel,上面有提到,我们只需要下面的2行代码即可处理:

titleLabel.backgroundColor = UIColor.white
titleLabel.layer.masksToBounds = true

通过去掉图片alpha通道优化后如下图所示,只有被设置为圆角的小图片还存在Blending,因为我们是直接设置的layer的cornerRadius(IOS9以下会导致离屏渲染),同样我们可以直接用无透明通道的圆角图片来替换解决,但这需要UI适配更多背景图片。
Blending优化后.png

2.光栅化

开启光栅化是通过设置属性shouldRasterize,开启光栅化后CALayer会被保存为bitmap放到缓存中,这样在下次需要时可以直接中缓存中取出来显示,这样节省了渲染时间,例如对于设置有阴影效果的复杂视图会对性能有一定的提升。

nameLabel.layer.shouldRasterize = true//开启光栅化

第二个调试选项 Color Hits Green and Misses Red就是用来查看光栅化视图的,勾选后若视图被标记为绿色,则表示命中了缓存,直接从缓存中取出来显示,缓存的有效时间为100ms, 而红色则表示没有命中。Demo中,我们对第2个Label开启了光栅化,滚动会发现被标记为绿色
光栅化.png

更新一个已光栅化的Layer会触发离屏渲染,所以选择哪些视图适合做光栅化需要根据场景权衡,光栅化适合那些布局复杂而不经常变动的视图,比如

  • 用于避免静态内容的复杂特效的重绘,例如UIBlurEffect
  • 用于避免多个View嵌套的复杂View的重绘。

同时注意缓存是有大小限制的,所以不要过度是使用光栅化,因为超过缓存大小会导致大量的离屏渲染。

3.颜色格式

Color Copied Images选项能标识出视图中不能被GPU处理的图片,因为来自网络的图片格式可能千变万化,有的图片的格式是GPU无法识别的所以会交给CPU处理,出现这种情况就需要修改图片格式,

4.不标准的表面颜色格式

Color Non-Standard Surface Formats 打开此选项后会发现Label会出现灰色的背景颜色,然后经过我们给Label设置了背景颜色后便消失了,关于此选项的相关介绍甚少,期待有人能挖掘挖掘,所以只能猜测,苹果推荐我们给Label设置一个背景颜色。
Non-Standard.png

5.颜色刷新频率

默认情况下图层的颜色更新是有10ms的延迟的,在某些特定情况下可能需要关闭这个延迟,但绝大多数情况用不到这个选项。

6.图片大小

Color Misaligned Images选项在图片像素不对齐(也就是图片带alpha通道)时,会在图片上面加一层洋红色来标识;而图片被缩放时,会加一层黄色来标识,我们可以看到优化前的图片会出现图片缩放,因为图片的显示大小和图片的大小不匹配。
Misaligned.png
图片缩放同样会消耗GPU资源,所以尽量保证图片的显示大小和原图大小一致来避免缩放,所以demo的图片在处理后大小都等于显示的大小来避免缩放。

7.离屏渲染

Color Offscreen-Rendered Yellow会用黄色标识哪些图层出现了离屏渲染,什么是离屏渲染?
离屏渲染表示渲染不是发生在当前屏幕的缓冲区中,而是发生在其他缓冲区的渲染,这就需要开辟更多的缓冲区,等到要用的时候再从其他的缓冲区读取来显示,所以这样会消耗更多的GPU资源,所以避免离屏渲染可以有效的提升显示性能。
离屏渲染.png
如上图所示,要显示一个相机图标和一个蒙层,在前两个渲染通道中,GPU分别得到了相机的纹理和蓝色的蒙版layer的渲染结果。但这两个渲染结果没有直接放入Frame Buffer中,这就是离屏渲染。等到第三个渲染通道,才把两者组合起来放入Frame Buffer中最终显示到屏幕上,这就是典型的离屏渲染。
运行demo,打开Color Offscreen-Rendered Yellow选项,在beforetab控制器视图下出现离屏渲染的图层便会被黄色标识出来,如图:
Offscreen.png
可以发现右边的大图出现了离屏渲染,而圆角的小图却没有,大图出现离屏渲染的原因是设置了shadow阴影,而因为测试机器是ios11所以设置图片的cornerRadius并不会导致离屏渲染。
同样设置了以下属性时,都会触发离屏渲染:

  • shouldRasterize(光栅化)
  • masks(遮罩)
  • shadows(阴影)
  • edge antialiasing(抗锯齿)
  • group opacity(不透明)
  • 复杂形状设置圆角等(ios8)
  • 渐变

上面出现离屏渲染的case都应该要注意,所以针对shadow可以通过设置shadowPath来避免,光栅化也应该尽量避免:
优化后代码如下:

        mainImageView.layer.shadowColor = UIColor.black.cgColormainImageView.layer.shadowOpacity = 1mainImageView.layer.shadowRadius = 2
//        mainImageView.layer.shadowOffset = CGSize(width: 2, height: 2)mainImageView.layer.shadowPath = UIBezierPath.init(roundedRect: mainImageView.bounds, cornerRadius: 2).cgPathsmallImageView.layer.cornerRadius = smallImageView.frame.size.width / 2smallImageView.clipsToBounds = truenameLabel.backgroundColor = UIColor.whitetitleLabel.backgroundColor = UIColor.whitetitleLabel.layer.masksToBounds = truenameLabel.layer.masksToBounds = true
//        nameLabel.layer.shouldRasterize = true

8.快速路径

第七个选项“Color Compositing Fast-Path Blue”用于标记由硬件绘制的路径,蓝色越多越好,demo略

9.变化区域

最后一个Flash Updated Regions 用于标记发生重绘制的区域并用黄色标记出来,对于大多数不变的区域应该尽量的避免重绘而只有小部分经常变化的区域重绘这有助于显著提高性能。demo略

优化结果

经过对图片Alpha透明度调整,大小剪裁适配显示,更改设置阴影,文本背景等一系列的优化,使用Core Animation记录GPU使用率的变化来观察优化效果:
before:
before.png
可以看到优化前CPU平均占用率达到60%,这还只是简单的视图布局,如果更加复杂占用率还会增加,这也就意味着更高的卡顿风险。

after:
after.png

对比可以发现在提升了平均显示帧数的同时大大降低了GPU消耗,性能得到显著的提升。

测试环境:Xcode9.3、iPhone6s、 iOS11、Swift4
Demo地址:GitHub地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

asp.net web api集成微信服务(使用Senparc微信SDK)

/// <summary>/// 微信请求转发控制器/// </summary>[RoutePrefix("weixin")]public class WeixinController : ApiController{#region 创建微信菜单/// <summary>/// 创建微信菜单/// </summary>/// <returns></returns>[HttpP…

1.SoapUI接口测试--创建项目

1、点击File-->New soapUI Project 2、填写项目名称&#xff0c;接口服务地址后单击【OK】按钮后就成功创建了一个项目 3、模拟发送请求 4、创建请求 或者直接Copy一个请求 5、保存项目 6、项目是以xml的格式保存的&#xff0c;下次用的时候可以直接导入&#xff0c;点击Fil…

Misc混合halcon算子,持续更新

目录convol_imageexpand_domain_graygray_insidegray_skeletonlut_transsymmetrytopographic_sketchdeviation_nconvol_image 功能&#xff1a;用一个任意滤波掩码对一个图像卷积。 expand_domain_gray 功能&#xff1a;扩大图像区域并且在扩大的区域中设置灰度值。 gray_i…

C/C++ 函数指针调用函数

01//C/C 函数指针调用函数 02#include<iostream> 03using namespace std; 04 05void site1() 06{ 07 cout<<"www.ok2002.com"<<endl; 08} 09 10void site2() 11{ 12 cout<<"www.ok1700.com"<<endl; 13} 14 15void…

汉字编码

汉字编码 一、汉字所占的字节数 对于一个字符串sizeof("请放手")&#xff0c;结果值是4。测试操作系统&#xff1a;Centos 6.4&#xff0c;硬件平台&#xff1a;Windows 7 32位 VirtualBox 4.3.12。看来用sizeof()来计算汉字所占用的字节或空间是不准确的。strlen(&…

Noise噪音halcon算子,持续更新

目录add_noise_distributionadd_noise_whitegauss_distributionnoise_distribution_meansp_distributionadd_noise_distribution 功能&#xff1a;向一个图像添加噪声。 add_noise_white 功能&#xff1a;向一个图像添加噪声。 gauss_distribution 功能&#xff1a;产生一…

sublime text3 package control 报错

安装sublime text3之后&#xff0c;安装package control 报错&#xff0c;错误信息&#xff1a;There are no packages available for installation 根据提示&#xff0c;找到错误解决办法&#xff1a;https://packagecontrol.io/doc... 其实意思就是你的电脑代理出了问题&…

HTML图片元素(标记)

<html> <head> <title>第一个网页</title> </head> <body> ***************图片元素******************</br> <img srcmm.jpg /> </body> </html> 新建一个文件夹“text”,在text文件夹内新建index.html并放入一张…

Optical-Flow光流halcon算子,持续更新

目录optical_flow_mgunwarp_image_vector_fieldvector_field_lengthderivate_vector_fieldoptical_flow_mg 功能&#xff1a;计算两个图像之间的光流。 unwarp_image_vector_field 功能&#xff1a;使用一个矢量场来展开一个图像。 vector_field_length 功能&#xff1a;计…

Oracle中procedure和function创建举例

Procedure创建与执行&#xff1a;Case1&#xff1a; create or replace procedure procedure_name(id user.table_name.columne_name%type)is begin delete from user.table_name where columne_nameid;exception when others then dbms_output.put_line(errors);end&#xff1…

Liunx 中tr的用法

1、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中cat /etc/issue |tr a-z A-Z > /tmp/issue.out2、将当前系统登录用户的信息转换为大写后保存至/tmp/who.out文件中who | tr a-z A-Z >> who.out3、一个linux用户给root发邮件&#xff0c;要who求邮…

ASP.NET Aries 3.0发布(附带通用API设计及基本教程介绍)

主要更新&#xff1a; 1&#xff1a;升级处理机制&#xff08;js请求由同步变更为异步&#xff09; 2&#xff1a;优化前端JS&#xff1a;包括API和配置方式。 3&#xff1a;增加InputDialog功能。 4&#xff1a;增远远程验证功能。 5&#xff1a;优化权限安全机制。 6&#xf…

多线程并发之原子性(六)

最近在网上找到好多的多线程关于原子性的例子&#xff0c;说的都不是非常的明确&#xff0c;对于刚学习多线程的新手而言很容误导学员&#xff0c;在这里&#xff0c;我通过多个例子对多线程的原子性加以说明。 例子一&#xff1a;传统技术自增 package face.thread.volatilep;…

Points角点halcon算子,持续更新

目录corner_responsedots_imagepoints_foerstnerpoints_harrispoints_harris_binomialpoints_lepetitpoints_sojkacorner_response 功能&#xff1a;在图像中寻找角点。 dots_image 功能&#xff1a;在一个图像中增强圆形点。 points_foerstner 功能&#xff1a;使用Frstn…

预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)

当 Visual C 项目启用了预编译头 (Precompiled header) 功能时&#xff0c;如果项目中同时混合有 .c 和 .cpp 源文件&#xff0c;则可能收到 C1853 编译器错误&#xff1a;fatal error C1853: pjtname.pch precompiled header file is from a previous version of the compiler…

甲骨文称 Java 序列化的存在是个错误,计划删除

甲骨文计划从 Java 中去除序列化功能&#xff0c;因其在安全方面一直是一个棘手的问题。 Java 序列化也称为 Java 对象序列化&#xff0c;该功能用于将对象编码为字节流...Oracle 的 Java 平台小组的首席架构师 Mark Reinhold 说&#xff1a;“删除序列化是一个长期目标&#x…

CreateProcess

Windows 进程创建完整过程&#xff08;除去细节&#xff09; 当前流程是分析WinXP x86得到的&#xff0c;在最新版本Windows上不一定正确&#xff0c;但是可以做一个参考&#xff0c; 由于我这里符号并不全&#xff0c;所以导致我这里有些东西看到的可能是错误的&#xff0c;误…

系统:Centos 7.2 内核3.10.0-327.el7.x86_64 # 内核需要高于2.6.32

系统&#xff1a;Centos 7.2 内核3.10.0-327.el7.x86_64 # 内核需要高于2.6.32 Drbd : 192.168.8.111&#xff1a;node1/dev/drdb0 /mydeta 192.168.8.112 : node2Mysql_vip: 192.168.8.200 #下章实现 # 需要的软件包&#xff1a;mariadb-5.5.53-linux-i686.tar.gzdrbd84-utils…

Smoothing滤波处理halcon算子,持续更新

目录anisotropic_diffusionbilateral_filterbinomial_filtereliminate_min_maxeliminate_spfill_interlacegauss_filterguided_filterinfo_smoothisotropic_diffusionmean_imagemean_nmean_spmedian_imagemedian_rectmedian_separate_median_weightedmidrange_imagerank_imager…

日志文件在VS中输出为乱码问题

原因&#xff1a;主要是文件文字格式问题&#xff08;使用使用 Unicode 字符集&#xff09;&#xff1a;修改项目/属性/常规/字符集/ 未设置