深入探讨如何从测试的角度对Webview进行压测并精准地分析Webview的内存情况

1.背景

背景是需要在移动端内嵌一个webview,这个webview的功能是通过长连接跟IM建联,完成类似于群聊天的功能,会有很多人发言,消息量预估是在1000左右,特殊场景是3000左右,消息内容包括图片、GIF、视频、文字。

2.技术方案

首先前端的资源通过调用IM中台的sdk获得,IM中台的资源由服务端1,服务端1从kafka拿消息,kafka里面的消息由服务端2发送。首先这个需求,我们面临的一个问题就是:1、怎么进行压测;2、怎么通过脚本的方式协助开发进行测试;针对这些问题,就需要写一个可以自动发消息的脚本。
于是通过python调用sendMessage接口来发送图片、GIF等消息,在这里又有一个问题,相同URL的图片、GIF发到前端是有缓存的,也就是说如果想要压测,那么必须使用不同域名的URL。这里又有2个方案。1、直接问服务端要他从数据库里面给我把这些资源导出来。2、去网站上爬图片,再转换成公司cdn地址,然后发到前端。很遗憾,最终只能选择第二种方案。
方案具体实施的步骤这里不细讲了。现在拿到了无限量的图片跟GIF,开始准备压测了。这里还有一个小插曲,当时由于发消息的频率没有控制,直接把公司测试环境的那台服务器压爆了(我没想到这服务器这么不抗揍),当时直接导致kafka消息积压(原因是消费端的qps限制是1,而我生成的速度远不止1),所以以后在做相关的压测的时候一定要注意控制发消息的频率。
现在到了正式执行压测的时候,为了测试极端情况,我直接上了5M大小的GIF,为了保证把一款中端机压爆,连续不停发1000条,在数量达到320条的时候,webview崩溃了。(后续有针对安卓、iOS的高中低端机型进行压测,发现安卓的高中低端机型都在300-400条GIF时发生崩溃,iOS则没有,iPhone确实很抗造)这时手机的内存情况是这样的:
内存变化趋势在这里插入图片描述
在这里插入图片描述
从图里面可以看到,随着GIF图数量的增加,手机的运行内存也在不断减少,直到一个临界点,会触发webview容器的保护机制(也就是崩溃)。到这,说明压测还是很有意义的,至少让我们试探到了极限在哪里,知道崩溃的标准才能根据实际情况去做相应的优化。
接下来就是对这个内存数据的分析。主要看2个指标,1、webview总内存;2、手机剩余内存。手机剩余内存就是目前可用的手机运行内存,webview总内存在下面详细介绍。

3.webview总内存的计算方式

webview总内存=native内存+gpu内存
native内存包括:v8、BlinkGC 、PartitionAlloc、DiscardableSharedMem、SharedMemory、malloc、fontcache、web_cache。
v8:V8 Javascript 引擎所管理,一般用于分配 Javascript 对象和数据。
BlinkGC:是标记式垃圾回收算法堆,一般用于管理页面运行上下文对象。
PartitionAlloc:为分桶式内存分配算法,用于解析、排版、页面运行上下文以及临时内存。
malloc:为类 libc 堆实现的仅用于 浏览器内核渲染引擎分配算法,缓存、页面运行上下文、临时内存都有用到。
SharedMemory: 为多进程共享内存。
DiscardableSharedMem :一般为图片解码缓存和 GL资源缓存等所用。

gpu内存包括:gpu、skia。(图片、GIF等绘制工作主要有图形处理器gpu完成,其余的解码等操作由cpu完成)
产生 GPU 内存的有三大来源:应用(非浏览器内核渲染引擎)本身、浏览器内核、页面 WebGL。其中页面 WebGL 的 API 调用产生的 GPU内存,由 Javascript 对象持有,随页面销毁而释放,属于页面运行上下文。Android 的应用其可以通过设置选项(一般都打开硬件加速合成)来配置 framework 使用硬件加速来合成 View 组件,而应用的 View Tree 越复杂则可能占用的 GPU 内存越多。浏览器内核维持着一定数量的 GL 资源缓存以渲染当前可见页面,随着页面越复杂,该占用越大。该占用为所有页面服务。简单的页面中,该占用仅几 MB。

4.在发送GIF的过程中内存是怎么变化的?

这个问题其实我自己也不是特别明白,如果有明白的朋友麻烦在评论区帮我纠正、补齐一下。我理解的webview内存应该是用来加载js对象、GIF资源解码数据、渲染等。而GIF本身的资源内存,比如5M,这个应该是存储在手机的运行内存里面。这些内存一般都会随着webview容器的销毁而释放。所以从上面压测过程的内存数据图可以看到,webview最终崩溃的原因是由于运行内存达到了一个阈值。
在这里native内存几乎没什么增长,可能是因为webview有缓冲池,gpu内存增长的来源主要是渲染GIF的损耗,主要是渲染带来的损耗。
如果内存的上升主要是native造成的,那么有可能是出现了内存泄露,因为native内存里面包括了v8引擎的数据内存。这种情况就可以通过Memory 面板证实。JS 占用的内存如果在我们重复会场间跳转操作时持续上涨,并且没有下降的趋势,那么就是出现了内存泄漏。

5.优化方案

从技术上来说,暂时有2种方案。1、将列表改造成虚拟列表;虚拟列表的缺点很明显,在数据量比较大的时候,如果快速上下滑,那么消耗的算力也是巨大的,而且不稳定,bug会比较多。优点同样明显,每次只维持固定数量的dom节点对象,可以极大地降低dom节点数量过大导致的卡顿。因为我们的场景数据量不是很大,没有上万,所以最终放弃了虚拟列表。2、设置一个阈值,因为消耗内存的主要是GIF,所以当GIF的数量达到一个阈值时将所有可视区域之外的GIF资源进行回收,防止崩溃。总的来说效果还可以。

总结

该文主要是为了记录一下这个项目,也是为了跟大家多多交流,希望大家提出建议,针对本文的不妥之处,还望指教。如果觉得有用欢迎转载。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值