前端监控和页面卡顿
Posted 恪愚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端监控和页面卡顿相关的知识,希望对你有一定的参考价值。
上一篇文章结尾提到了一个对图片(图片!不是图像!)至关重要的点:采样、量化和编解码。
图像的显示需要GPU和CPU两者配合,CPU主要负责视图的创建,布局的计算和视图的绘制,然后进行图片的解码,将生成的位图交给GPU,GPU进行渲染,并将渲染的结果交到帧缓冲区,待下一个VSync 信号到来的时候视频控制器从帧缓冲区取出数据,经过转换,显示到屏幕上。
如果在规定的16.7ms
内,CPU和GPU的合作未完成,没有生成新的渲染数据到帧缓冲区中,那么就会出现卡顿或者掉帧的情况。
一般我们常说的“精灵图”Sprite 其实不止优化了“网络请求”,也利用了这一点,“尽量避免短时间内大量图片的显示,尽可能将多张图片合成一张进行显示”。
除了上面提到的“图片加载”导致的页面卡顿。引起页面卡顿的场景还有很多。大致有两类:
- 渲染引起的卡顿
- 内存引起的运行卡顿
为了用户体验考虑,我们需要对这些现象进行上报,以便更快、有针对性的进行优化和修复。
其中第一种情况又有:“资源引起的页面掉帧”、“页面 FPS 持续低于预期”、“交互行为引起的渲染问题”。
卡顿严格来说还分为“正常卡顿”和“真实卡顿”(这里“真实”的意思是达到需要上报条件的)。而我们需要上报的就是“真实卡顿”。比如:
- 在页面 FPS 连续
n 秒
内低于一个值时; - 当用户进行交互行为后,渲染新的一帧的时间超过
16ms + 100ms
时; - web worker心跳检测(针对页面崩溃!)
想想看,我们可以把“页面崩溃异常”也归为“页面卡顿”。这样的话就可以统一在某些行为不及预期时上报它们。
以上这些已经属于“错误上报”的范畴了。而我认为,一定要区分开错误上报和数据埋点(也叫埋点上报),这两者有本质区别和各自界定分明的作用场景。
页面崩溃这种行为通常是两种场景导致的:
- 过长时间占用JS线程(我们可以把它叫做“主线程”),比如无限循环,触发了浏览器的保护策略;
- 内存不足
这么看来页面崩溃就是一个“过火了”的“页面卡顿”。
在这两种场景中,毫无疑问主线程被阻塞,因此对崩溃的监控只能在独立于 JS 主线程的 Worker 线程中进行,我们可以采用 Web Worker 心跳检测
的方式来对主线程进行不断的探测,如果主线程崩溃,就不会有任何响应,就直接进行崩溃异常的上报。
比如我们可以这么设置:
对JS 主线程:固定时间间隔向 Web Worker
发送心跳
对Web Worker
线程:
- 每隔固定时间检查是否收到心跳(这个间隔和主线程发送心跳的间隔一致);
- 超过一定时间(间隔时间+n秒)未收到心跳,则认为页面崩溃。
- 检测到崩溃后,通过 http 请求进行异常上报。
上面的流程是以主线程优先。当然,你也可以换一种思路:
// 主线程
var worker = new Worker('worker.js');
// 父给子传一个初始时候的标志位
worker.postMessage(-1);
worker.onmessage = function(e)
//收到worker线程传来的消息
console.log('Message received from worker', e.data);
worker.postMessage(e.data);
// 子线程
let date_begin = null;
let dTip = 0;
let newTip = 0;
let new_led = 0;
setInterval(()=>
if(!newTip && date_begin || !new_led)
// 被认为是崩溃
else
new_led = 0;
postMessage(++dTip);
,2000)
onmessage = function(e)
let d = Date.now();
if(e.data < 0)
newTip = 1; //修改标志位确认符
date_begin = d; //初始化时间
return
if(d - date_begin > 4000)
// 被认为是崩溃
else
date_begin = d;
new_led = 1;
也可以用socket,不过没啥必要,又不是高频强交互行为。而且这里都直接用公司内部封装好的错误上报API了吧。不过像是服务端状态改变实时通知可以试试在 webworker 中使用socket,不过,为什么不试试http/2
的 SSE 呢?
除了页面卡顿。前端监控还应涉及视觉、交互、请求、资源、环境、稳定性、网络等方方面面,才能为用户体验打造一个良好的基础。
以上是关于前端监控和页面卡顿的主要内容,如果未能解决你的问题,请参考以下文章