美文网首页weex优化
iOS集成Weex内存优化最牛逼方案

iOS集成Weex内存优化最牛逼方案

作者: 五八四十 | 来源:发表于2018-02-08 11:55 被阅读0次

前言

引入weex提高了业务开发的效率以及灵活度,但是在使用过程中还是存在不少问题,其中内存上就有很明显的问题

一、weex页面与原生页面对比存在的内存问题

1、weex页面内存开销过大

如图进行页面切换:

Weex-iOS内存分析

在进行到weex页面的时候内存暴涨。

2、页面Push跳转堆栈内存泄漏。

从首页Push跳转到weex页面,加载数据,再返回,重复多次得出下图的结果:

Weex-iOS内存分析

而Push跳转到原生页面再返回,重复多次得出下图内存结果:

Weex-iOS内存分析

从上面两张图可以看出:原生页面返回后从堆栈移除后会进内存回收;而从weex页面回到首页,内存没有完全回收,存在一定的内存泄漏,重复多次可以看到内存相比较一开始会有明显的增加。

3、列表滑动的内存情况

在没有采用 <list style="box-sizing: border-box;">和<cell style="box-sizing: border-box;">标签的情况下:</cell></list>

weex页面列表滑动内存情况如图:

Weex-iOS内存分析

weex页面滑动内存情况

通过趋势图列表滑动过程中内存一直持续暴涨,没有进行复用减少内存开销。

原生页面列表滑动内存情况如图:

Weex-iOS内存分析

原生页面滑动内存情况

从图中可以看到,在滑动初始阶段,内存增长比较快,之后的滑动过程中对前面的控件进行复用,内存开销减少,曲线变得平缓,没有出现内存持续暴涨。

4、 weex页面内存问题总结

  1. weex页面滑动没有采用复用机制,导致内存会跟着滑动持续暴涨

  2. weex页面占用内存开销过高,多个weex页面可能导致APP因为内存过大而Crash。

  3. weex页面从堆栈移除内存没有完全回收,存在一定的内存泄漏。

二、内存问题原因分析

1、滑动过程内存持续暴涨问题

weex官方文档上,建议使用高性能可复用<cell style="box-sizing: border-box;">和 <list style="box-sizing: border-box;">,而【搜索页】、【乐疯抢】等weex页面业务代码中直接采用了</list></cell>

和<scroller style="box-sizing: border-box;">实现列表的布局,导致内存问题的出现。</scroller>

这里我们通过Weex源码,对四个标签进行分析

可以在WXSDKEngine 中可以看出各个标签对应的类:

Weex-iOS内存分析

<pre style="box-sizing: border-box; overflow: auto; font-family: "courier new"; font-size: 12px; display: block; padding: 10px 20px; margin: 20px 0px; line-height: 20px; color: rgb(51, 51, 51); word-wrap: break-word; background-color: rgb(245, 245, 245); border: none; border-radius: 4px; font-style: normal; font-variant: normal; font-weight: 400; font-stretch: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">?对应WXComponent对应WXScrollerComponent对应WXCellComponent对应WXListComponent</pre>

对应的WXComponent 相当于原生iOS控件的UIView,是所有视图的基类,一个普通的视图没有性能优化、复用回收的机制。

<scroller style="box-sizing: border-box;">对应的WXScrollerComponent结构如下:</scroller>

Weex-iOS内存分析

并无相关复用回收的属性,主要是提供一个可以滑动的容器。

查看<cell style="box-sizing: border-box;">对应WXCellComponent类的实现代码可以发现,WXCellComponent相比较WXComponent 拥有复用回收的相关属性isRecycle</cell>

Weex-iOS内存分析

<list style="box-sizing: border-box;">对应的WXListComponent的结构如图:</list>

Weex-iOS内存分析

在成员列表中可以看到使用了iOS原生的UITableView,并且实现了使用了UITableView的代理方法,实现了iOS的复用机制,如图:

Weex-iOS内存分析

同时WXListComponent实现了WXCellComponent中的代理方法,WXCellComponent与WXListComponent相关联系。

Weex-iOS内存分析

因此 <list style="box-sizing: border-box;">基于iOS的UITableView复用机制,实现高性能了可复用的列表容器。</list>

结合<cell style="box-sizing: border-box;">可以实现一个高性能的列表展示页面。</cell>

因此采用 <list style="box-sizing: border-box;">和<cell style="box-sizing: border-box;">代替<scroller style="box-sizing: border-box;">和</scroller></cell></list>

解决滑动列表内存暴涨的问题。

2、weex页面内存开销过高的问题

通过Instrument工具进行内存分析,发现在进入weex 页面时VM ImageIO_GIF_Data和VM ImageIO两个对象内存异常暴涨。

VM ImageIO_GIF_Data 内存增长情况:

Weex-iOS内存分析

VM ImageIO 内存增长情况:

Weex-iOS内存分析

VM ImageIO_GIF_Data 由7.92M增长到16.55M,VM ImageIO由0.11M增长到了1.02M,进入Weex页面时,这两个对象总共增加了9.54M,而整个Weex页面初始状态占用内存为15M左右(原生【商品详情】页:7M左右),占据了整个Weex页面内存的约60%。

而在原生页面中,VM ImageIO_GIF_Data和VM ImageIO对象几乎没有增长。

而这两个对象与CoreGraphics中进行图片绘制、图片渲染、图片读写等相关方法有关,而CoreGraphics为相对底层的模块,相关方法比较消耗性能、内存,并且容易产生内存泄漏。

初步可以判定,weex中大量调用了CoreGraphics中图片处理的相关方法,导致了weex页面内存开销过大。

接着在WeexSDK的源码中查找CoreGraphics相关方法,定位问题。

在查找过程发现,weex通过CoreGraphics绘图方法将<text style="box-sizing: border-box;">等控件实例绘制成位图进行显示,以适应weex中的CSS布局。</text>

在 WXComponent+Display 中,可以看到将控件绘制成图片的代码,并在layer上显示:

Weex-iOS内存分析 Weex-iOS内存分析

通过这部分的代码可以定位到weex页面内存开销过大的主要原因是: weex SDK 调用了CoreGraphics方法将页面中的<text style="box-sizing: border-box;">等控件绘制成图片再布局显示,占用了大量的内存。</text>

weex的内存泄漏也与大量调用了CoreGraphics中方法有关。

通过Leaks工具定位到weex页面内存泄漏对象为CGDataProviderCreateWithCopyOfData

Weex-iOS内存分析 Weex-iOS内存分析

而CGDataProviderCreateWithCopyOfData为调用CoreGraphics相关方法产生的对象。

weex SDK调用CoreGraphics中的相关方法,但是没有及时地释放对象,导致了内存泄漏。

weex SDK 大量CoreGraphics方法将控件绘制成图片再布局显示,占用了大量的内存,同时也导致了资源回收不及时的问题。

解决方案:

  1. 限制堆栈中weex页面个数:

    天猫采用的也是该方案,通过控制页面级数,控制内存,防止因为堆栈过多的weex页面,内存过大导致异常Crash。

  2. 页面复用:

    在打开weex页面前,判断堆栈中是否有该weex页面,如果有便进行页面复用,通过数据刷新页面,同时通过调整堆栈将页面显示出来。

重点总结:

开发过程中也曾因为内存消耗过大而苦恼,那就是人人畏惧的Crash!!!
为什么内存吃的如此之大?巅峰都能超过1G内存!于是我静下心来准备做点大事情!!!
虽然没有做到优化达到极致但起到了效果,具体几点详细介绍如下:
1.Weex加载长列表的时候是否采用复用?
2.Weex长列表滑动时是否限制数据加载模式?
3.Weex页面回退是否做了一系列的内存回收?
4.缓存你做了么?
5.接收到内存警告的时候你做了什么处理?
6.尽可能重写一些Weex实现的容器,方便管理!
以上几点可以作为一个切入点!感觉可以深入的路还很长。
经过一系列的优化与重写方法目前内存峰值基本保证在150M左右,不过我还会继续优化!!!后续有好的方法还会更新最新优化方法。
看过感觉有用记得关注,有好的建议可以提出来!一起成长!!!Go!

相关文章

网友评论

    本文标题:iOS集成Weex内存优化最牛逼方案

    本文链接:https://www.haomeiwen.com/subject/oqhgzxtx.html