兩份效能報告對同一件事給出不同的數字。原因不在量測,在 Git —— 今天與昨天所有的效能成果只存在負責人這台機器上,遠端只看得到其中一條。barry 正是在那唯一一條上接續開發,所以他手上是一份缺了 13 條成果的視圖。
分支本身沒有壞掉,壞掉的是「誰看得到什麼」。實作者的 14 條效能分支全部未 push,barry 只拿得到 feat/ext-render-worker-replay 那一條並在上面繼續做。結果是兩邊在同一塊成本上各做了一套解法,而且 barry 的報告裡有一項結論(「預烘骨骼淨值 0ms、不採用」)在我們這邊已經被推翻了。
其餘的不是已經合進 main(73 條),就是 7 月的舊工作分支(52 條,內容都已在 main 裡或已被放棄)。下面三群是現在還有活內容、還沒進 main 的。
| 分支 | 裡面是什麼 | 領先 main | 能不能用 |
|---|---|---|---|
| feat/impl-baked-more-types @72bf1e94 |
累積線,包含下面所有東西:相位分桶、描邊併材質群組、陀螺批次化、預烘骨骼(man/girl/dog)、轉頭改 5 矩陣、髒標記三本帳、10 套骨架不掛進 scene | 22 | 可用 工作樹乾淨,功能與正確性已驗完 |
| feat/impl-integration @2331735e |
整合驗證點 —— barry 報告裡「整合分支 −2.23ms」量的就是這條 | 14 | 可用 但已被上面那條吃掉 |
| feat/impl-baked-head-fix | 轉頭從「每頂點混合」搬到「每隻怪 5 個矩陣」 —— 這顆解掉了 barry 報告裡說「預烘不適用」的那個理由 | 19 | 可用 已被累積線包含 |
| feat/impl-bench-scene feat/impl-pose-phase-buckets feat/impl-bucket-roundrobin feat/impl-zombie-outline-group feat/impl-baked-bone-man feat/impl-dirty-flags 等 |
累積線的中間節點 | 12–20 | 歷史 不用單獨動,但先別刪(A/B 對照要用) |
| 分支 | 裡面是什麼 | 推了沒 | 能不能用 |
|---|---|---|---|
| feat/ext-render-domfree | 渲染層拆掉 DOM 依賴(第一階段) | 未推 | 可用 |
| feat/ext-render-worker-replay | 錄影重播進 Worker(第二階段) | 已推 | 可用 ⚠️ 遠端已被 barry 續寫 6 顆 |
| feat/ext-render-worker-zombies | 10 種怪進 Worker、逐像素零差異(第三階段) | 未推 | 可用 |
| feat/ext-render-worker-live @61089ea4 | 活遊戲每幀送進 Worker(第四階段) | 未推 | 可用 暫停中,成果完整 |
| 分支 | 裡面是什麼 | 狀態 |
|---|---|---|
| origin/feat/ext-render-worker-replay | 我們的 8 顆 + barry 的 6 顆。barry 直接接在我們第二階段的頭上 | 要處理 見第二節 |
| origin/feat/pixi-ui-migration | Pixi HUD 測試碼 | 待驗收 落後 main 43 顆 |
| origin/feat/lead-android-gpu-trail-opt origin/feat/kiro-android-perf-opt | WebGL2D 與 prefab cache 優化 | 已進 main |
它們只存在負責人這台機器的 .git 裡。這台機器出事=昨天與今天全部的效能成果歸零,包含 4 項優化、預烘骨骼、多執行緒四個階段、量測台。
建議先推上去再談其他事。推分支不影響任何人(不合併就不會動到 main),成本是一個指令。
barry 的 6 顆 commit 加在 feat/ext-render-worker-replay 上,動到 5 個生產檔:
| 檔案 | 行數 | 內容 |
|---|---|---|
| ZombieAdapter.ts | +125 | 精準骨架矩陣(避開整棵 FBX 樹的 updateMatrixWorld 遞迴) |
| PropAdapter.ts | +74 | 陀螺差異更新 |
| PerfDiagnostics.ts | +154 | 新檔 · 逐步驟計時系統 |
| GameRenderer.ts / RenderPipeline.ts / PerfConfig.ts | +70 | 接線與開關 |
| scripts/*.mjs | +873 | Android A/B 自動化與深度診斷腳本 |
| 項目 | 收益 | 他自己的判定 |
|---|---|---|
| 精準骨架矩陣 | −1.79ms (31.41→29.62) | 最有價值;但視覺壞掉未修 |
| 陀螺差異更新(疊加) | −0.44ms | 有效但小 |
| state.reset 收窄 | +0.12~0.19ms | 無效益,建議維持現狀 |
| 全部組合 | −1.91ms (31.41→29.50) | fps 31.9 → 33.9 |
「精準矩陣有視覺問題尚未修復。橄欖球員頭部扭曲、木乃伊手指不動、部分怪物抬頭未生效 —— 根因是 Three.js Skeleton.bones[] 不保證父骨先於子骨,現行實作直接依此順序算 matrixWorld,造成末端骨骼讀到上一幀的值。」
⇒ 那 1.79ms 目前不能算進帳。
| 項目 | barry 的報告(192.168.5.18) | 我們今天的結論 | 誰比較新 |
|---|---|---|---|
| 預烘骨骼 | 「淨值 0ms(省的 CPU 被轉頭 GPU 成本抵銷)」「預烘會犧牲即時轉頭,暫不採用」 | 轉頭已改成「每隻怪 5 個矩陣」,不再犧牲轉頭;新量測台上 Δp50 4.5ms | 我們 |
| 四項優化合計 | 相位分桶 −1.29/陀螺批次 −1.04/描邊 −0.58/精準矩陣 −1.85 | 今天用新量測台重驗:相位分桶重現(1.1ms),預烘大 3.3 倍,另兩項還沒重驗。「合計 4.28ms」已作廢 | 我們 |
| 整幀基準 | baseline 31.41ms、整合後 25.5ms、缺口 8.3ms | 正式版打包、釘住場面:一般幀 32–34.5ms、缺口 15–18ms | 條件不同,不是誰對誰錯 —— 見下方 |
| Worker 多執行緒 | 「+2.52ms,待每幀傳遞成本量完才算」 | 同一個數字,而且已經知道它救不了 60fps:整幀 ≈ Worker 渲染 23.4ms + 0.15ms 交接,主線做什麼都不影響 | 我們 |
它的開頭「three.js 11.1ms + 原生 GL 5.6ms = 16.7ms,剛好等於整個 58fps 預算,我們自己的遊戲邏輯只有 4ms」是我們 8/4 報告同一段話的改寫(數字全部相同、句子重新斷過)。所以這不是兩份互相競爭的報告,是同一份的兩個版本 —— 他的版本多了 Cocos 機制對照與 P0/P1/P2 路線圖,少了今天下午之後的所有更正。
他的腳本註解寫的目標是 http://localhost:3000/?auto=1&webgl2d=1。而 3000 埠服的是 C:\temp\board-run\dist-A。
實測那份 dist:App chunk 1,858,718 bytes,而同一支程式的正式版打包只有 1,479,239 bytes(差 400KB);dist-A 還帶著只有開發版才會產生的 *.ui.js chunk。⇒ dist-A 與 dist-B 兩份都是開發版。
開發版多兩個 rAF 迴圈,其中一個每秒一次讓整棵 React 重畫,單次 60–77ms。
他量到 p99 = 77.33ms,優化後 73.50ms —— 尾巴幾乎沒動。如果尾巴來自 React 全樹重畫,那正是他的優化碰不到的東西,行為完全吻合。
要確認很簡單:問他實際跑的是哪個 port/哪個 dist。如果是 3000,那組數字的絕對值不能代表玩家。
他的「Perf Panel 開關影響排序」裡,關掉特效 −3.62ms、關掉障礙物 −3.67ms、關掉票券數字 −3.63ms —— 關掉工作反而更慢,物理上不可能。他自己註記了「測量噪音」。
那代表這個台子的噪音底大約 ±4ms。所以「殭屍 +10.84ms」方向大概是對的,但「佔 36.8%」這個精度撐不住。(對照:我們今天建的量測台三輪全距 0.6ms,因此規定 1.5ms 以下不准單組宣稱。)
| 指標 | 第一張表 | 第二張表 | 矛盾在哪 |
|---|---|---|---|
| zombie.sync | 1278.9ms 總 / 8.5ms 幀 | 11.34ms | 第一張表推出 instances 佔 sync 的 96%,第二張表推出 12% |
| zombie.instances | 1233.2ms 總 / 1.5ms 隻 | 1.33ms |
而「zombie.instances 是主要瓶頸」這個結論是從第一張表推出來的。兩張表的分母(樣本數)不一致 —— 1233.2÷1.5≈822 次,667.8÷0.16≈4174 次,差 5 倍。建議請他先對一次計時器的計次口徑。
更直接的證據:barry 在他的「後續方向」寫「動畫快取/預烘焙(但頭骨需要動態 look-at,可能不適用)」—— 那正是我們昨天做完並且已經解掉的東西(feat/impl-baked-head-fix,轉頭改成每隻怪 5 個矩陣)。他看不到那條分支,所以把它列成待研究方向。
| # | 動作 | 為什麼 | 成本 |
|---|---|---|---|
| 1 | 把 14 條效能分支 push 上去 | 目前只有一份拷貝;而且 barry 看不到成果才會重工 | 一個指令,不動 main |
| 2 | 把「預烘 head-fix 已解掉轉頭問題」告訴 barry | 他正把它列為「可能不適用」的待研究方向 | 一則訊息 |
| 3 | 問 barry 三個問題(第四節) | build 種類、噪音底、計時口徑 —— 三個都會改變他報告的結論 | 一則訊息 |
| 4 | 把精準矩陣與預烘骨骼放在同一個量測台上比一次 | 兩種打法打同一塊錢,要選一個,不能兩個都算 | 一輪派工 |
| 5 | 刪掉 73 條已合進 main 的舊分支 | 純整潔,不影響任何內容 | 一個指令 |