CPU 上的 JavaScript 把每一幀的時間預算花光了。 最大的兩塊正是蔡點名的順序 —— 殭屍(算 26 隻怪的骨頭要擺哪,7.15ms)與 畫面(three.js 畫之前的準備工作,6.15ms),合計 66%。 而「不知道的部分」已經查完了,沒有黑洞;顯示晶片反而一直在等我們,只佔 4%。
量測場面一幀 20.25ms(看比例,不看絕對值):
| 區塊 | 內容 | 毫秒 | 佔比 |
|---|---|---|---|
| 殭屍 蔡排第 1 ✓ |
把遊戲狀態算成畫面。 算動畫播到第幾格 3.40 + 骨頭換算世界位置 2.55 + 送 GPU 0.75 + 其餘 1.95。 錢在「算」不在「送」(5.95 vs 0.95)。 |
7.15 | 35% |
| 畫面 蔡排第 2 ✓ |
three.js 真正畫出來。 52% 是每次繪製前的材質/骨骼狀態準備、41% 是排序與可見性、7% 才是 GL。 真正的繪圖指令只佔 7% 的九分之一。 |
6.15 | 30% |
| 其他 | 已拆完,最大單項 1.0–1.7ms。沒有大塊、沒有黑洞。 | 5.35 | 26% |
| 遊戲邏輯 | 玩法本身的運算。 | 0.85 | 4% |
| 等顯示晶片 蔡排第 3「未知」→ 已歸零 ✓ |
GPU 一直在等 CPU 餵資料。瓶頸完全不在顯示晶片。 | 0.75 | 4% |
這點有三組互相獨立的證據:
所以「少生一點怪」「合併繪製批次」這兩個直覺方向都已被實測否決。
上線那 3.5ms 之後,還差 7.2–9.6ms。只剩兩條路:
| 路線 | 做法 | 能拿回 | 風險 |
|---|---|---|---|
| 多執行緒 | 把「畫面準備」整段搬到另一條執行緒 | ≤ 6.15ms | 現有 Worker 雛形自己要跑 22.7–29.3ms,要重做資料流才拿得到 |
| WASM | 把「算骨頭」用更快的方式重寫 | ~3ms | 上界 3.3–4.1ms,實得倍率沒有實測 |
兩條加起來 9.15ms,缺口 7.2–9.6ms ⇒ 順利剛好夠,不順利差一點。而且「兩條相加」本身沒被驗證過。
⇒ 所以下一步不是直接投入,是 各花一天做原型買到真實數字。
目前 23.9–26.3ms,已經在 30fps 的預算(33.3ms)內。走這條的話,問題就換成消掉頓挫:
| # | 項目 | 成本 | 玩家有感 | 改幀率 |
|---|---|---|---|---|
| 1 | 把已寫好的 3.5ms 合進 main | 搬運 | 是 | 是 |
| 2 | 載入修正核可(已完成:−1.47 秒、−144MB,畫面已驗無差異) | 核可 | 是 | 否 |
| 3 | 貼圖預載(消頓挫) | 2–3 天 | 是 | 否 |
| 4 | 多執行緒/WASM 各做一天原型 | 2 天 | 否 | 買數字 |
1、2、3 玩家馬上有感但不改平均幀率;4 才碰得到 60fps。
一、作者一開始漏讀了最權威的那份文件。8/6 的板子總報告(約 30 輪實測)是整個議題的權威文件,而前三份報告是在沒讀它的情況下寫的。根因是拿一個停在舊 commit 的工作目錄當 main 的代理 —— 那個目錄只有 11 份報告,main 實際有 21 份。發現後全部重寫。
核心結論(殭屍第一、per-object 成本是根本機制)碰巧存活,但作者自評「那是運氣不是流程」。
二、數字是 8/6 的。之後 main 前進了 300 多顆 commit,今天的版本沒有人量過。方向性結論穩,毫秒數要打時間折扣。
三、原始量測資料不在 repo 裡(在負責人本機與 gitignore 的工作區),所以這份整合報告無法複驗那些數字,只能轉述。