cpu耗时操作
布局计算 —视图层级过于复杂,当视图呈现或者修改的时候,计算图层帧率就会消耗一部分时间
视图懒加载
Core Graphics绘制 - 如果对视图实现了-drawRect:方法,或者CALayerDelegate的-drawLayer:inContext:方法,那么在绘制任何东西之前都会产生一个巨大的性能开销。
解压图片 - iOS通常直到真正绘制的时候才去解码图片,,对于一个较大的图片,都会占用一定的时间。
GPU 耗时操作
太多的几何结构
为什么离屏渲染会发生卡顿?主要包括两方面内容:
创建新的缓冲区。
上下文切换,离屏渲染的整个过程,需要多次切换上下文环境(CPU渲染和GPU切换),先是从当前屏幕(On-Screen)切换到离屏(Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上又需要将上下文环境从离屏切换到当前屏幕。而上下文环境的切换是要付出很大代价的。
离屏渲染的优化建议
使用ShadowPath指定layer阴影效果路径。
使用异步进行layer渲染(Facebook开源的异步绘制框架AsyncDisplayKit)。
设置layer的opaque值为YES,减少复杂图层合成。
尽量使用不包含透明(alpha)通道的图片资源。
尽量设置layer的大小值为整形值。
直接让美工把图片切成圆角进行显示,这是效率最高的一种方案。
很多情况下用户上传图片进行显示,可以在客户端处理圆角。
使用代码手动生成圆角image设置到要显示的View上,利用UIBezierPath(Core Graphics框架)画出来圆角图片。
合理使用光栅化 shouldRasterize
光栅化是把GPU的操作转到CPU上,生成位图缓存,直接读取复用。
优点:
CALayer会被光栅化为bitmap,shadows、cornerRadius等效果会被缓存。
缺点:
更新已经光栅化的layer,会造成离屏渲染。
bitmap超过100ms没有使用就会移除。
受系统限制,缓存的大小为 2.5X Screen Size。
shouldRasterize适合静态页面显示,动态页面会增加开销。如果设置了shouldRasterize为YES,那也要记住设置rasterizationScale为contentsScale。
过大的图片 - 如果视图绘制超出GPU支持的2048x2048或者4096x4096尺寸的纹理,就必须要用CPU在图层每次显示之前对图片预处理,同样也会降低性能。
不要用JPEG的图片,应当使用PNG图片。
子线程预解码(Decode),主线程直接渲染。因为当image没有Decode,直接赋值给imageView会进行一个Decode操作。
优化图片大小,尽量不要动态缩放(contentMode)。
尽可能将多张图片合成为一张进行显示。
减少透明 view
使用透明view会引起blending,在iOS的图形处理中,blending主要指的是混合像素颜色的计算。最直观的例子就是,我们把两个图层叠加在一起,如果第一个图层的透明的,则最终像素的颜色计算需要将第二个图层也考虑进来。这一过程即为Blending。
会导致blending的原因:
UIView的alpha<1。
UIImageView的image含有alpha channel(即使UIImageView的alpha是1,但只要image含有透明通道,则仍会导致blending)。
为什么blending会导致性能的损失?
原因是很直观的,如果一个图层是不透明的,则系统直接显示该图层的颜色即可。而如果图层是透明的,则会引起更多的计算,因为需要把另一个的图层也包括进来,进行混合后的颜色计算。
opaque设置为YES,减少性能消耗,因为GPU将不会做任何合成,而是简单从这个层拷贝。
超大图导致的内存暴增,carsh ,解决:
SDW 中 decodeImageWithImage这个方法用于对图片进行解压缩并且缓存起来。
解压缩操作中,每一个像素点都会分配一个空间来存储相关值,那么分辨率越高的图片,就意味着更多数量的像素点,也就意味着需要分配更多的空间!所以对于高分辨率图来说,如果缓存解压缩之后的数据,即使是几M的图片,也是有可能消耗上G的内存!
解决:在需要下载高分辨率图的地方,避免--缓存解压缩后的数据操作,手动关闭SDWeb缓存方法。大图加载后再手动打开
离屏渲染,页面卡顿常见问题以及解决:
iOS 保持界面流畅的技巧 | Garan no dou AsyncDisplayKit 框架学习
解码操作:
一般我们使用的图像是JPEG/PNG,这些图像数据不是位图,是经过编码压缩后的数据,需要将它解码转成位图数据,才能把位图渲染到屏幕上。
用 UIImage 或 CGImageSource 的那几个方法创建图片时,图片数据并不会立刻解码。图片设置到 UIImageView 或者 CALayer.contents 中去,并且 CALayer 被提交到 GPU 前,CGImage 中的数据才会得到解码。这一步是发生在主线程的,并且不可避免。
iOS默认是在主线程解码,所以SDWebImage将这个过程放到子线程了。同时因为位图体积很大,所以磁盘缓存不会直接缓存位图数据,而是编码压缩后的PNG或JPG数据。
超大高清图处理:
使用SDWebImage下载高分辨率图,导致内存暴增的解决办法 - 简书
“压” 是指文件体积变小,但是像素数不变,长宽尺寸不变,那么质量可能下降。
“缩” 是指文件的尺寸变小,也就是像素数减少,而长宽尺寸变小,文件体积同样会减小。
iOS压缩图片的两种方式 - 简书 系统自带压缩图片质量 & 压缩图片大小,对图片进行裁剪
iOS 图片压缩处理 - 简书 两种压缩方式详解和对比。
高清大图分片压缩:
大文件分片上传:大文件分片上传 & 断点续传
将大图分解成小片然后将他们单独按需载入。在多个线程中为每个小块同时调用 -drawLayer:inContext: 方法。这就避免了阻塞用户交互而且能够利用多核心新片来更快地绘制。只有一个小块的 CATiledLayer 是实现异步更新图片视图的简单方法。
网友评论