衡量一个weex页面质量的角度有很多种,不管哪种角度,都是为了在端侧给用户更好的体验。
通常来说,用户接触最频繁、影响最大、感受最明显的是页面的加载时间。在之前的版本中,weex提供了首屏时间这个概念,来衡量这个时间。但是随着业务复杂度的增加,引入底图、框架壳子,首屏越来越有局限性,只能算是加载时间的一部分,并不能作为度量整个加载时间的指标。
目前业务的逻辑大概是
老的秒开时间最多只能监测到第3步的时间,但是业务方真正想要的、和用户感官最接近的应该是第5步完成的时间
因此,我们做了两件事,来处理这个问题
推出可交互时间
这个指标,来衡量 开始渲染到屏幕(instance
)内view稳定渲染完成的时间 (开始渲染bundle—>异步请求—>屏幕内view树稳定、渲染完成)
修正首屏算法,使用新的字段newFSRenderTime
来作为新的首屏指标 (老首屏字段不受影响)
如上所示,可交互时间的起始点分别是
对于起始点,应该没什么疑问,对于结束点的两个限定条件,做一些说明。
可交互时间是对首屏时间的补充,首屏后,因为有异步刷新的缘故,view还是会不断增删刷新,所以第一个限定条件是 屏幕内view树且稳定下来,不再出现增删的操作。
定义可交互的时候,碰到一个问题,什么时候算是可交互呢?
如上所述,无论是渲染到什么程度,事实上都是可以交互的。
最后选择屏幕内所有view渲染完成这个结点(图3)作为约束的边界点
回想一下可交互时间的两个限制条件
所以思路很简单,当屏幕内发生view的add/rm操作时,认为是可交互点,记录数据。直到没有再发生为止。
实现过程中,碰到3个bad case
这几个case的解决方案如下,如果大家有更好的想法,可以提出来
iOS 代码实现
//when addview,call _handleRenderTime - (void) _handleRenderTime:(WXComponent*)targetComponent withModifyTime:(double)modifyTime { //超过8s不再记录 double diff = modifyTime - self.renderTimeOrigin; if (diff > 8000) { return; } // 去除不必要的多余计算 if (diff < self.interactionTime) { //useless calulcate ,for imporove performance return; } //有点击事件,直接返回 UIView *root = targetComponent.weexInstance.rootView; if (root && [root isKindOfClass:[WXRootView class]]) { WXRootView* wxRootView = (WXRootView *)root; if ([wxRootView isHasEvent]) { return; } } //屏蔽fix元素 if ([targetComponent.isfix]) { return; } CGRect absoluteFrame = [targetComponent.view.superview convertRect:targetComponent.view.frame toView:targetComponent.weexInstance.rootView]; CGRect rootFrame = targetComponent.weexInstance.rootView.frame; CGPoint leftTop = absoluteFrame.origin; CGPoint rightBottom = CGPointMake(absoluteFrame.origin.x+absoluteFrame.size.width, absoluteFrame.origin.y+absoluteFrame.size.height); bool inScreen = CGRectContainsPoint(rootFrame, leftTop) || CGRectContainsPoint(rootFrame, rightBottom); //屏幕外的view,不care if (!inScreen) { return; } //更新可交互时间 self.interactionLimitAddOpCount++; self.interactionAddCount = self.interactionAddCountRecord; self.interactionTime = self.interactionTime < diff ? diff :self.interactionTime; }
系统 | 系统版本 | 机型 |
---|---|---|
iOS | 11.2 | iPhone 8 |
Android | 8.0 | 华为P10 |
摄像机帧率50,即20ms/帧
业务 | 埋点时间 | 摄像机拍摄体感时间 | 网络时间 | 误差 |
---|---|---|---|---|
有好货Android | 2297 | 2900 | 16 | -20% |
有好货iOS | 1437 | 1300 | 8 | 11% |
有好货Android | 5678 | 5960 | 96 | -3% |
头条iOS | 529 | 660 | 8 | -18 |
天天特价Android(首次) | 3831 | 4440 | 100 | -13% |
天天特价iOS(首次) | 1308 | 1500 | 144 | 3% |
天天特价Android(非首次) | 3288 | 3480 | 60 | -4% |
天天特价iOS(非首次) | 1280 | 1460 | 74 | 6% |
爱逛街Android | 2463 | 2240 | 20 | 10% |
爱逛街iOS | 830 | 940 | 16 | -10% |
展示三个测试case。
天天特价iOS(首次)
有好货Android
爱逛街iOS
有同学可能问了,衡量指标给了,那有没有优化的建议或者参考信息呢
当然有的,不都讲究一条龙服务吗 (手动滑稽.jpg)
github 地址:https://github.com/weexteam/weex-devtool-iOS
整体耗时:
详细view渲染到屏幕上的时序
weex在统计可交互时间的同时,同时记录了以下几个辅助信息数据
字段 | 含义 | 备注 |
---|---|---|
wxInteractionComponentCreateCount | 可交互时间内,创建component个数 | 创建组件要耗时的 肾5s上,3ms/个 |
wxInteractionScreenViewCount | 可交互时间内添加view的次数(屏幕内) | 屏幕内view,直接影响可交互时间结果 |
wxInteractionAllViewCount | 可交互时间内添加view的次数 (屏幕内+屏幕外) | 参考数据 不影响可交互时间 但不建议在屏幕外创建大量组件,耗时又耗内存 |
在讲首屏修正方案之前,先回忆下现在的前端逻辑
前面说过,老版首屏最多能监控到第3步的情况。实际上。在业务支撑过程中,发现第3步时未必到达用户真实“首屏”感受
鉴于以上case,修正了首屏时间的算法
新的字段newFsRenderTime
作为新的首屏参考 老字段不受影响
测试数据比较,以iOS数据为例,如下图所示
算法和数据结果如上文所述,这里放一张图总结一下首屏(老)、首屏(新)、可交互时间的覆盖范围
欢迎广大业务方来提改进,和bad case 优化可交互时间的算法
毕竟业务认可的,和实际感官相符的,才是正确的。