笔者经常与微信手Q平台打交道,偶尔会遇到 H5 页面导致 iOS 下微信手Q程序闪退(崩溃)的情况。
导致微信手Q闪退的原因笔者遇到的大概有以下几种:
- CSS-3D 加速过多;
- 带滚动条的结构过多;
- webGL 绘制图像过多
本文仅讨论「CSS-3D」加速造成微信手Q闪退的必要条件」。
科普一下「CSS-3D加速」也叫「CSS硬件加速」,它的原理是利用 GPU加速图像渲染。每一个带有 3D 属性的 DOM 节点都会在 GPU 生成一个对应的纹理,而这个纹理可以被快速地操作(如:移动、缩放和旋转)。GPU纹理会占用一定的内存,而微信手Q分配给内嵌 webview 的 GPU 内存是固定的,一旦GPU纹理超过了这个内存就将导致所在环境闪退(崩溃)。
微信手Q分配给 GPU 纹理的内存是多少?
老实说,笔者不了解微信手Q的内核,所以回答不了。不过,既然GPU纹理超过指定内存就会闪退,那么可以通过实验的方法推导出闪退的临界值。
带 3d 样式的 DOM 节点与 GPU 纹理的面积大小是一一对应的,所以笔者直接用 「width * height px2」 描述 GPU 纹理的大小。
安全值实验
为了方便计算,笔者使用尺寸为 100px * 100px
的 div 作为实验对象,样式如下:
.rect {
width: 100px;
height: 100px;
transform: translateZ(0);
}
具体的实验案例笔者放在:https://leeenx.github.io/demo...。二维码如下:
笔者手头上只有 iPhone6 & iPhone6+,测试的数据如下:
设备 | APP环境 | rect 数量 | 描述 |
---|---|---|---|
iPhone6 | 手Q | 1400 ~ 2700 | 第一次进入不闪退,刷新当前页面闪退 |
iPhone6 | 手Q | >2700 | 进入直接闪退 |
iPhone6+ | 手Q | 700 ~ 1400 | 第一次进入不闪退,刷新当前页面闪退 |
iPhone6+ | 手Q | >1400 | 进入直接闪退 |
iPhone6 | 微信(UIWebview) | 1400 ~ 2700 | 第一次进入不闪退,刷新当前页面闪退 |
iPhone6 | 微信(UIWebview) | >2700 | 进入直接闪退 |
iPhone6+ | 微信(UIWebview) | 700 ~ 1400 | 第一次进入不闪退,刷新当前页面闪退 |
iPhone6+ | 微信(UIWebview) | >1400 | 进入直接闪退 |
iPhone6 | 微信(WKWebview) | 100000+ | 不闪退 |
iPhone6+ | 微信(WKWebview) | 10000+ | 不闪退 |
注意事项:
- 测试页面的「生成」按钮会刷新后重新生成对应个数的 rect
- UIWebview 是指微信旧的webview,具体可以参见:iOS网页开发适配指南
微信环境下有个利好的消息:
微信iOS客户端将于2017年3月1日前逐步升级为WKWebview内核
也就是说「3d加速」已经不会造成新版微信闪退了。坏消息是手Q仍然有闪退的风险。
通过上面的数据其实可以找到 iPhone6/6+ 的闪退临界值为:1400 * 100 * 100 px2 与 700 * 100 * 100 px2
但是其实我们可能需要的是安全值而不是临界值,笔者根据自身经验定了一个安全值:
- iPhone6 3D加速的安全面积:
1000 * 100 * 100 px2
- iPhone6+ 3D加速的安全面积:
500 * 100 * 100 px2
由于我们的页面都会在 iPhone6 & iPhone6+ 上运行,所以真正的 「安全值是 500 * 100 * 100 px2
」。
500 * 100 * 100 px2 有多大?
iPhone6+ 的 webview 尺寸是:414 * 736,那么「500 * 100 * 100 / 414 * 736 ≈ 16」。也就是说「3d加速的安全面积是16个手机屏幕」。这个尺寸并不大,所以加速需小心,安全最重要。
可能会有人会想iPhone6+闪退的门槛比 iPhone6 低这么多?
iPhone6 和 iPhone6+ 官方配置上除了屏幕之外,其它硬件是同样的配置,所以有这样的疑问其实很正常。很明显 iPhone6 与 iPhone6+ 闪退门槛的差异源自物理屏幕。
iPhone6 的 dpr = 2, iphone6+ 的 dpr = 3;而 GPU 纹理是按物理分辨率存储的。假设一个带
3D 样式的 div 的尺寸为 100px2,那么这个节点在 iPhone6 对应的 GPU 纹理为 「2 * 2 * 100px2」,在 iPhone6+ 对应的 GPU 纹理为 「3 * 3 * 100 px2」。
很容易可以得到以下的数字:
3 * 3 * 100 px2 / 2 * 2 * 100px2 = 2.25
2.25 就是 iPhone6 与 iPhone6+ 的 GPU 加速的门槛差,其实通过上面的数据也反映了类似的比率。
结语
本文出示的数据是非生产环境下得出来的,真实的生产环境会受其它外因的影响估计数据要再打一下折。
感谢耐心阅读完本文章的读者。本文仅代表笔者的个人观点,如有不妥之处请不吝赐教。