Screen Test Pro

打造一個永遠不會卡死的瀏覽器基準測試

作者 Screen Test Pro發佈於

基準測試會以各種尷尬方式失敗:進度卡在 97%,連續執行分數相差 30%,甚至因為筆電螢幕更好而給它更低的分數。為 2.0 重寫測試時,我們把這份故障清單貼在桌前,逐項設計應對方案。以下是開發過程中的一些記錄。

把測量倒過來

傳統基準的結構是「固定工作負載 + 測量 FPS」,但放進瀏覽器後幾乎沒有意義。高效能裝置很快就會頂到螢幕更新率(瀏覽器不會快於垂直同步繪製,於是所有好裝置都只報告「60」或「120」);低效能裝置則變成投影片,測到的是使用者耐心,而不是效能。

所以我們改為固定目標——16.67 毫秒影格預算——把工作負載設為變數。每個場景逐步提高粒子數量,直到影格時間超出預算;隨後透過二分搜尋找到邊界,再要求候選負載連續三個視窗乾淨通過。最後得到的「最大穩定負載」有直觀的物理意義:這台裝置最多能推動 840,000 個星雲粒子而不開始掉影格。

倒置測量從結構上就能優雅應對弱裝置:它不會跑出一個損壞的結果,只會停在同一把負載梯子的較低一級。

使用百分位數,因為卡頓會騙過平均值

每個視窗既要檢查平均影格時間,也要檢查第 95 百分位數。設定 p95 門檻,是因為平均值會替卡頓洗白:一台裝置有 95 個影格準時、5 個影格耗時 40 毫秒,平均資料可能仍然漂亮,體感卻很糟。百分位門檻能把「感覺很差」變成可測數字。單次異常視窗(例如通知或垃圾回收暫停)會重試,而不是直接計為失敗;但連續失敗兩次就會否決該負載。它會原諒意外,不會原諒規律。

近乎多疑的狀態機

「不能卡死」的要求催生了專案中最不光鮮、卻最關鍵的一段程式碼。每個場景都會經過狀態機——預檢、基準、預熱、爬升、夾逼、確認、錨點——而且每個狀態都有明確出口:

  • 每個場景最多 30 秒,整次執行最多 150 秒,沒有例外;
  • 切到背景會作廢目前測量視窗並暫停;隱藏超過 30 秒,測試會以明確原因結束;
  • 視窗大小或像素比變化時,系統會重建場景並重新預熱,不會拿垃圾資料計分;
  • WebGL 上下文遺失、GPU 卡住(數秒沒有新畫面)、場景拋出錯誤,各自對應獨立的退出原因;即使渲染迴圈停擺,看門狗計時器仍會繼續運作;
  • 在以上每一種狀態中,Escape 都能退出。只有一切正常時才有效的取消按鈕,不能算取消按鈕。

測試可以提前結束、帶著效能下降標記結束,也可以被取消;唯一不會發生的事情,是永遠停在那裡。

誠實面對溫度

持續 GPU 負載會加熱裝置,裝置升溫後會降速;忽略這一點的基準,只會悄悄把機器最好的一分鐘和最差的一分鐘揉進平均值。因此,每個場景都會兩次測量輕量基準——開始一次、結束一次。如果第二次慢 15% 以上,該場景就會被標記為效能下降;標記會保留在結果和分數中(扣分有上限),如果使用者提交樣本,也會進入資料集,讓公開中位數可以排除熱降頻測試,而不是把它們吸收進去。

公平對待高更新率

這裡有個不明顯的陷阱:如果按各自更新間隔判斷,120Hz 筆電必須在 8.3 毫秒內繪製每個影格才算「跟上更新」,承擔的要求是 60Hz 裝置的兩倍。我們的預算對所有裝置都固定在 16.67 毫秒。高更新率螢幕仍能展現優勢(輕負載時顯示更多畫面),但不同面板的及格線完全相同。顯示器是觀看方式的選擇;基準測試的任務,是測量它背後的電腦。

我們有意沒有加入的東西

目前沒有 WebGPU——將來若加入,它也會作為獨立設定,擁有自己的計分空間,絕不會在同一個數字下面悄悄替換實作。本版本也沒有使用 Web Worker 渲染:Worker 終止、上下文轉移、跨執行緒輸入等額外故障面,與「永不掛起」的要求相衝突,而兩種方案的受測工作負載相同。最後,在匿名資料集達到真正有意義的樣本門檻前,結果頁不會聲稱任何百分位排名——拿 40 次測試計算百分位,只是給感覺套上一件數字外衣。

包括計分公式在內的完整規範,已寫在方法說明中。如果你發現任何裝置不符合上述保證,那就是程式錯誤,請聯絡 admin at screentest.pro。