CSS-3D 加速导致微信手Q闪退

笔者经常与微信手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...。二维码如下:

CSS-3D 加速导致微信手Q闪退_第1张图片

笔者手头上只有 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+ 不闪退

注意事项:

  1. 测试页面的「生成」按钮会刷新后重新生成对应个数的 rect
  2. 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 加速的门槛差,其实通过上面的数据也反映了类似的比率。

结语

本文出示的数据是非生产环境下得出来的,真实的生产环境会受其它外因的影响估计数据要再打一下折。

感谢耐心阅读完本文章的读者。本文仅代表笔者的个人观点,如有不妥之处请不吝赐教。

你可能感兴趣的:(ios,bug,手机qq,微信)