天天看點

前端監控和頁面卡頓

上一篇文章結尾提到了一個對圖檔(圖檔!不是圖像!)至關重要的點:​​采樣、量化和編解碼​​​。

圖像的顯示需要GPU和CPU兩者配合,CPU主要負責視圖的建立,布局的計算和視圖的繪制,然後進行圖檔的解碼,将生成的位圖交給GPU,GPU進行渲染,并将渲染的結果交到幀緩沖區,待下一個VSync 信号到來的時候視訊控制器從幀緩沖區取出資料,經過轉換,顯示到螢幕上。

如果在規定的​​

​16.7ms​

​内,CPU和GPU的合作未完成,沒有生成新的渲染資料到幀緩沖區中,那麼就會出現卡頓或者掉幀的情況。

一般我們常說的“精靈圖”Sprite 其實不止優化了“網絡請求”,也利用了這一點,“盡量避免短時間内大量圖檔的顯示,盡可能将多張圖檔合成一張進行顯示”。

除了上面提到的“圖檔加載”導緻的頁面卡頓。引起頁面卡頓的場景還有很多。大緻有兩類:

  1. 渲染引起的卡頓
  2. 記憶體引起的運作卡頓

為了使用者體驗考慮,我們需要對這些現象進行上報,以便更快、有針對性的進行優化和修複。

其中第一種情況又有:“資源引起的頁面掉幀”、“頁面 FPS 持續低于預期”、“互動行為引起的渲染問題”。

卡頓嚴格來說還分為“正常卡頓”和“真實卡頓”(這裡“真實”的意思是達到需要上報條件的)。而我們需要上報的就是“真實卡頓”。比如:

  • 在頁面 FPS 連續​

    ​n 秒​

    ​内低于一個值時;
  • 當使用者進行互動行為後,渲染新的一幀的時間超過​

    ​16ms + 100ms​

    ​時;
  • web worker心跳檢測(針對頁面崩潰!)

想想看,我們可以把“頁面崩潰異常”也歸為“頁面卡頓”。這樣的話就可以統一在某些行為不及預期時上報它們。

以上這些已經屬于“錯誤上報”的範疇了。而我認為,一定要區分開錯誤上報和資料埋點(也叫埋點上報),這兩者有本質差別和各自界定分明的作用場景。

頁面崩潰這種行為通常是兩種場景導緻的:

  1. 過長時間占用JS線程(我們可以把它叫做“主線程”),比如無限循環,觸發了浏覽器的保護政策;
  2. 記憶體不足
這麼看來頁面崩潰就是一個“過火了”的“頁面卡頓”。

在這兩種場景中,毫無疑問主線程被阻塞,是以對崩潰的監控隻能在獨立于 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;
    }
}      

繼續閱讀