ITPub博客

首页 > 应用开发 > IT综合 > iOS端的直播软件源码可以对页面如何进行优化

iOS端的直播软件源码可以对页面如何进行优化

IT综合 作者:云豹科技阿星 时间:2021-11-02 16:59:49 0 删除 编辑

关于直播软件源码页面的性能优化,我们能做些什么?个人想了一下,能想到的就是以下几点:

  • 优化布局计算

  • 异步进行耗时操作

  • 解决图片问题(对于 APP来说,图片是造成内存问题的最大瓶颈点)

  • 避免离屏渲染

优化布局计算

关于 auto layout的布局,直播软件源码最直接的优化是使用手动布局计算 frame。

因为自动布局的原理是:通过创建一个与 view绑定的对象 engine,使用 engine记录下来相关的约束信息,在布局计算的时候,带入相关参数计算出来 frame.

如果能去掉这一步,肯定是能节省性能的。

虽然 iOS 12系统之后,苹果对 auto layout进行了优化,优化后的效率和手动布局差不太多。但是我们的用户还是会有很多在12系统以下的。

因此,还是可以考虑优化的。

不过我目前还没有遇到过使用 auto layout造成页面性能出现问题的案例。

异步耗时操作

图片解码操作

图片为什么需要解码?

首先直播软件源码里的本地图和加载过来的网图,都是经过压缩的二进制数据(常用的 jpg, png)。

在显示到界面上的时候,需要将这些二进制数据绘制到对应的“画布”上。

这个绘制的过程就是解码。

image.png

异步图片解码

系统会默认在 UIImage加载到 UIImageView或者 CALayer的 content上的时候,在主线程进行解码。

这个解码操作是耗时的,如果不处理可能会造成卡顿问题,因此需要放到子线程里去异步执行。

我们使用的三方框架都有此类处理。

比如 SDWebImage是创建了一个串行队列,异步执行解码操作。

通过 SDWebImageAvoidDecodeImage参数可以控制是否进行解码操作。

不过这里有个疑惑,为什么不使用并发队列?使用串行队列就意味着图片解码操作要顺序执行,这样效率岂不是有点低?

缓存高度

对于不同 cell的滑动列表,可以利用缓存来避免多次计算,达到提效的目的。

可以做的简单点利用数据模型来持有这些信息。

也可以利用三方的框架: UITableView+FDTemplateLayoutCell

解决图片问题

图片占有内存问题

从上图可以看到,图片占用内存的大小计算方式是: width * height * 每个像素占用的内存大小(一般是4字节)

一张图,如果分辨率比较大,就容易造成很大的内存问题

当页面上有多个图片的时候,这个内存就会暴增。

避免无谓的解码操作

SDWebImage在加载图片的时候默认会进行解码操作。

网上随便找了三张图,使用 SDWebImageManager去加载。在开启和关闭解码操作后,在开启解码操作的时候,内存占用了 10M。 关闭解码操作的时候,内存占用了 5M。

使用第三方库的时候,如果只是预加载图片,可以考虑设置不解码。

DownSampling(向下采样)

image.png

DownSampling 就是在 Decode的时候指定尺寸,只 Decode部分数据,减少内存的使用。

比如我一个控件大小是 100 * 100,但是原图可能是 300 * 300的。使用 DownSampling后,只需要解码少量数据就可以达到所需。

这个 SDWebImage也已经支持,大家只需在加载图片的时候,利用 context参数设置图片的大小和控件的大小相同即可。

@{SDWebImageContextImageThumbnailPixelSize:@(size)}
复制代码

image.png

经过我的实验,效果还是很明显的。

网上找了 6张大图。

在不进行 DownSampling的情况下,加载 6张图片都消耗了 25M

image.png

但是在使用 DownSampling的时候,指定尺寸为 100*100,内存直接降低到了 5M

image.png

目前运用到直播软件源码的首页Feeds流上,效果很显著。在只加载不到三屏的情况下(一屏大概4-6张图),都节省了 40M左右。

注意使用的时候传入的尺寸要考虑到高清屏的系数。

因此,我们在搭建界面的时候,尽量加载和控件一样大的图,否则可能你看到的只是一个小图,其实占用了很大的内存,同时还需要 CPU帮你去做一些压缩,剪裁的工作。

建议使用 Image Assets去管理

  • 查找快

    如果是放到bundle里,是需要遍历bundle的文件夹。但是 Image Assets的查找做了优化。

  • 更加智能的缓存策略

  • 可以减少拆分后的包体积

  • 支持图片拉伸等特性。

减少 Backing Store的使用

什么是backing store?

CALayer的 contents所指向的区域。

如果使用了 draw函数, CALayer会创建一个与 view相同尺寸的 Backing store,在上面进行 draw的操作,然后提交到 frame buffer中用于渲染。

这一步会造成内存的消耗。

因为系统的 UILabel对单色的 string做了优化处理,可节省75%的 Backing Store,并能自动更新 Backing Store的 size以适配 富文本或 emoji。

对于一些复杂的 view样式,可以通过多个 subView组合到一起来实现,尽量减少 draw的操作,就可以减少这部分内存的消耗。

图片复用

对于纯色图片,尽量复用一个图片,用 tint Color 来进行不同的渲染。达到复用图片的目的。

对于直播软件源码使用频繁的图片,可以使用 [UIImage imageWithNamed:@""]方式创建,利用系统级别的缓存来提高效率,减少内存。

对于使用不频繁的图片,建议使用直接读文件的方式加载,用完就会自动释放,减少内存。

离屏渲染

什么是离屏渲染?

正常情况下,直播软件源码会按照 60FPS或者 120FPS的频率来执行渲染流程。

在每个屏幕渲染周期内,系统会从帧的缓冲区里拿到已经渲染好的数据,渲染到屏幕上。

而由于图层或者其他因素,导致在屏幕内无法直接渲染,需要在屏幕外开辟一个空间用来合成帧数据。

这就是所谓的离屏渲染。

离屏渲染的坏处

离屏渲染之所以不好,原因是:

1.开辟了一块额外的空间,内存增加了

2.切换环境造成的牺牲很大

很容易发生在渲染周期内,数据无法渲染好,因此造成卡顿问题。

造成离屏渲染的方式

关于离屏渲染,实际开发中基本上都是:

  • 圆角+剪裁的组合

  • 设置layer的mask

  • 设置阴影

  • 光栅化

  • 抗锯齿

解决离屏渲染

对于设置阴影造成的离屏渲染,解决方式就是使用贝塞尔曲线绘制好 path,这样就能解决问题。

这里想更多的介绍一下圆角方面的优化。

对于 UIImageView的圆角方案

最开始的时候,我的想法和网上的方案一样,就是:

利用子线程将图片进行切角处理,同时缓存下来这张图片,然后异步到主线程使用图片。这样就可以解决了圆角的离屏渲染问题。

但是在实际操作过程中,觉得这一步还是有问题的。

问题一:内存占用增加

在滑动列表里,我们不可能一直不停地对图片进行切圆角操作。

不然就需要一直消耗 CPU进行切圆角操作,还要频繁切换线程。

因此,我们就需要使用空间换时间了,将切好的圆角图片也缓存下来。

这个时候问题来了:一张图,被网络框架加载并存储了一份,现在又存下来了一张圆角图片

那基本上意味着内存占用double了一下。

问题二:实现功能很容易,但是想写好太难

虽然网上给出了很多的demo,但是在我看来写的都不好。

  • 首先,很粗暴的放到了一个全局并发队列里进行绘制,没有考虑到线程的消耗和安全问题。

  • 其次是没有一个很完善的防重用逻辑。

    一般我们都是使用的滑动视图,里面 cell上的控件都是会重用的。如果不像 SDWebImage一样先将之前的获取图片操作移除,如何确保重用的时候不出问题?

  • 使用起来麻烦

    如果自己实现了一套获取图片的逻辑,会发现代码量增加很多,远远不如使用 SDWebImage分类来的方便。(当然我们自己也可以使用一个分类来完成这个任务)

上面说的这些问题,其实都可以通过扩展 SDWebImage来支持。

但是需要花费时间和精力来搞定,未来有机会的话,可以尝试一下。

我认为的圆角最优解

对现在有的机器(iphone 11)进行了简单的验证,使用异步绘制圆角图片的方案解决离屏渲染后,通过 instrument的分析,发现 CPU和 GPU都没有一个很明显的收益变化。

如果非得优化,让设计师切一个遮罩盖在上面是我认为的最好的解决方案。

毕竟前面也提到了,苹果认为组合 subViews的方式比直播软件源码自己绘制的方式好很多。
声明:本文由云豹科技转发自雨天多久就博客,如有侵权请联系作者删除


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69982461/viewspace-2840268/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2020-08-24

  • 博文量
    239
  • 访问量
    115536