無線效能優化:FPS測試
時間回到幾周前,這天,女神突然來找我,“我這裡有幾個頁面想測量下頁面滾動的順暢性,你有啥辦法不?”。Are you kidding me?這麼簡單,簡直是道送分題啊,於是當著女神面,開啟 Chrome 開發者工具,勾選上 Show FPS meter,醒目的 FPS 監控皮膚就出來了,滑動頁面時 FPS 的曲線就基本反映出了頁面滾動的順暢性,坐等女神的誇獎~~
“這個我知道啊,但是我有好多頁面,難道要一個一個人工看嗎?而且這個也沒有一個記錄的匯出,如果能有個方法幫我自動的測量,有問題再通知我,我再仔細排查就好了”。
這個需求開始有點技術含量了,不過應該也難不倒我,頁面都接入了 UITest,在頁面做 UI 測試的時候,跑一下測量 FPS 的測試用例就 ok 了,那如何測量呢?女神等我~~
mozPaintCount
mozPaintCount 變數是 Mozilla 提供的方法,其返回的是當前文件 paint 到螢幕上的數量,通過計算單位時間 paint 數量變化,即可計算出頁面的 FPS,so easy。
等等,這個變數目前好像只有 Firefox 支援,Chrome 上並沒有一個 webkitPaintCount 或者 paintCount 變數,而我們的 UITest 是跑在 ChromeDriver 或者 PhantomJS 上,並沒有 Firefox 環境,好吧,這個可以做備選方案,依賴於 UITest 支援 Firefox 環境。為了完成女神的需求,我們還要考慮其他方案了。
requestAnimationFrame
在頁面重繪前,瀏覽器會執行傳入 requestAnimationFrame 的入參函式,一般多用來實現連貫的逐幀動畫。那我們基於 requestAnimationFrame 不就可以獲得頁面的繪製頻率,計算出 FPS,而且瀏覽器支援情況也不錯,說幹就幹,示例程式碼如下(簡單示例,沒做相容等處理):
var lastTime = performance.now(); |
用例結果如下:
大功告成,可以去找女神答覆了,等等,這樣是不是太簡單了點,無法讓女神刮目相看啊(在女神面前裝逼),我們是不是再深入點。
Chrome 瀏覽器渲染頁面時,涉及了兩個執行緒,Render 主執行緒和 Compositor 合成執行緒,且兩個執行緒通過名為 Commit 的訊息來保持同步,而每一幀消耗時間應該是包含兩部分,Render 主執行緒消耗的時間和 Compositor 執行緒消耗的時間。典型的狀態如下(以下三張圖片來自 frame-timing-polyfill):
主執行緒 Commit 訊息提交給合成執行緒,任務都在 16.66ms 內完成。當然,對於一些輸入事件,比如滾動,是先轉移給合成執行緒進行處理,然後通知給主執行緒,這樣可以保證對使用者的輸入操作做及時的響應,同時,對於一些頁面更新,如 CSS 動畫和 CSS 濾鏡,只需合成執行緒處理,而無需請求主執行緒,如下所示:
當然,也有可能,主執行緒處理耗時較多,導致提交給合成執行緒的時間推遲到了下一幀,如下所示:
針對以上三種情況,那流暢性如何定義呢?就需要因地制宜,不同環境分別分析了。
-
對於滾動和 CSS 動畫,由於不涉及主執行緒的影響,我們會更關心合成執行緒的繪製頻率,而合成執行緒的繪製頻率也反映了滾動和 CSS 動畫的流程性。
-
對於 JS 幀動畫而言,我們期望主執行緒和合成執行緒的消耗加起來到能在 16.66ms 內,且不丟幀。因此我們需要同時關注主執行緒的 Commit 頻率和合成執行緒的繪製頻率,並且我們期望每個主執行緒的 Commit 都對應唯一一個合成執行緒的繪製(保證不丟幀)。
那是否有方法可以讓我們分別取到 Render 主執行緒和 Compositor 合成執行緒的資料呢?答案是 Frame Timing。
Frame Timing
Frame Timing API 目前還只是草案,暫時還沒發現有瀏覽器支援,不過我們可以先實現,萬一瀏覽器支援了呢~~,目前的 API 如下:
var rendererEvents = window.performance.getEntriesByType("renderer"); |
獲取 Render 主執行緒和合成執行緒的記錄,每條記錄包含的資訊基本如下:
{ |
每個記錄都包括唯一的 Frame Number、Frame 開始時間以及持續時間。根據 duration 就可以知道該幀是否達到 16.66ms 的標準,同時根據單位時間記錄數(Frame)的個數就能算出主執行緒或者合成執行緒每秒的幀率。
同時,對於主執行緒 Commit 給合成執行緒繪製的情況,可以根據唯一的 sourceFrameNumber 將 renderEvents 的記錄和 compositeEvents 的記錄做關聯,得出每個主執行緒 Commit 所對應的合成執行緒繪製的次數,如前所說,這也是判斷 JS 動畫流程性的一個可檢測指標~~(具體實現程式碼較多且比較簡單,就不貼了,小夥伴們動動腦筋,分分鐘就寫出來了~)
至此,終於可以向女神交差了,想想女神崇拜的目光,還有點小激動呢~~
再等等,既然 Chrome 能開啟 FPS meter,而且我們的 UI 測試也是跑在 ChromDriver 中的,那是不是可以通過配置開啟 Chrome 的 FPS meter 獲取到 FPS 呢,女神,再等我下~
Show FPS Counter or Performance Log
果不其然,查詢 ChromeDriver 的配置設定
–show-fps-counter: Draws a heads-up-display showing Frames Per Second as well as GPU memory usage. If you also use –vmodule=”head*=1” then FPS will also be output to the console log.
只要能輸出到 console log 裡,我們就能方便的取到了,於是果斷在 UITest 的 ChromeDriver 配置里加上裡這兩項:
chromeOptions["args"] = [
// 其他配置省略
`--show-fps-counter`,
`--vmodule="head*=1"`
];
滿心歡喜的一試,FPS meter 是出來的,但是說好的 console log 並沒有,具體的討論可以參見這個 issue。
難道沒有別的辦法了嗎?既然 Chrome 的 Timeline 那麼強大,其中也包含了每一幀的耗時,那是不是可以取到 Timeline 的資料?當然沒問題,我們使用 selenium-webdriver就能方便的獲取到頁面的 Performance Log,示例如下所示:
var webdriver = require(`selenium-webdriver`); |
其中,traceCategories 的配置和 chrome://tracing/
的配置一樣,開啟 Chrome,位址列輸入 chrome://tracing/
,點選 record
按鈕,會出現如下所示的配置項:
其中的配置就是我們可以獲取的。獲取到 Performance Log 後匯出成 JSON 檔案,匯入到 Chrome 的 Timeline 裡,你會驚奇的發現,這和直接用 Timeline 效果是一樣一樣的,如下所示:
但是接下來,我發現真正頭疼的問題來了,Performance Log 是一堆密密麻麻的資料,而且還沒找到相關文件,目前只是可以取出平均的 FPS,計算方法如下,首先解析資料,取出型別為 DrawFrame 的記錄個數,然後除以整個統計的持續時間,即可大體得出整體平均的 FPS,如何解析出更具體的資料,還在持續研究中,希望這下可以讓女神滿意,嘿嘿嘿~
參考文件
- Measuring FPS
- frame-timing-polyfill
- ChromeDriver Config
- issue: need FPS data in console log
- selenium-webdriver
- selenium-webdriver api
相關文章
- 前端效能優化之效能測試前端優化
- 無線效能優化:Composite優化
- 測量、基線和效能優化之三:基於測量、基線和變化的效能優化優化
- 測量、基線和效能優化之三:基於測量、基線和變化的效能優化v優化
- [原創]ETL效能測試和優化優化
- 測量、基線和效能優化之二:基線和效能優化
- Python Django 效能測試與優化指南PythonDjango優化
- 無人值守自動化效能測試平臺
- sqlldr效能調優測試SQL
- 效能測試之測試分析與調優
- [總結]無線測試
- 【效能調優】效能測試、分析與調優基礎
- Redis Enterprise新版優化線性擴充套件,效能測試有點厲害!Redis優化套件
- Anandtech:測試顯示蘋果新款無線基站效能顯著提高NaN蘋果
- ClickHouse效能優化?試試物化檢視優化
- ClickHouse 效能優化?試試物化檢視優化
- 功能測試、自動化測試、效能測試的區別
- postgresql無序uuid效能測試SQLUI
- 軟體效能測試的優勢
- 優先佇列的效能測試佇列
- 無線適配智慧化測試-以影像識別之名
- JNI/NDK開發指南(9):JNI呼叫效能測試及優化優化
- ACK G2-TA-KT執行無線效能測試操作步驟
- 效能測試知多少---效能分析與調優的原理
- JICMAIL:2021年A/B測試優化郵件效能報告AI優化
- 無線效能優化:頁面可見時間與非同步載入優化非同步
- JavaScript無阻塞載入效能優化方案JavaScript優化
- 談最佳化無線網路效能
- 【前端效能優化】vue效能優化前端優化Vue
- 我眼中的 效能劣化、優化的曲線優化
- 我眼中的效能劣化、優化的曲線優化
- Oracle高水位線(HWM)及效能優化Oracle優化
- 一次效能測試調優總結
- LoadRunner長連線效能測試指令碼指令碼
- 【效能測試】使用ab做Http效能測試HTTP
- 測試平臺後端優化後端優化
- 測試金字塔新解之移動無線應用測試
- Flutter 應用效能檢測與優化Flutter優化