iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
Modern Web

Vue 演進驗證 × AI Coding 時代的工程實踐系列 第 9

Day 9:Vue 3.6 Validation - Reactive Chain 的 Runtime 成本真的改善了嗎?

  • 分享至 

  • xImage
  •  
同一個 Reactive Chain,只換 Vue 版本,Runtime 的成本真的變了嗎?

今天只改一件事 Vue 版本 Vue 3.5.40 → Vue 3.6.0-rc.2,其他的 Reactive Chain 的程式碼不動,實驗參數不動,Browser 不換。

// vue@3.5.40 -> vue@3.6.0-rc.2
npm install vue@3.6.0-rc.2

再用相同參數跑 DEPTH = 100 ,且每次連續 Trigger Update 100 次,主要觀察 Update Duration、Computed、Watch、WatchEffect、Render 在 Vue Runtime 的行為有沒有真的改變?

第一輪數據 Vue 3.6 竟然慢了 157.7%!


第一次跑完,數字非常醒目:

Metric Vue 3.5.40 Vue 3.6.0-rc.2
Average Update Duration 4.729 ms 12.188 ms
Computed 10,100 10,100
Render 199 199

Update Duration +157.7%,不降反增,跟預期落差很大,所以開始回到過去檢視所有流程包含量測系統,避免造成誤會。

一個意外讓實驗停了下來


重新檢查 Claude Code 的自動化流程時,發現一個非常關鍵的資訊:

document.hidden
        ↓
      true
        ↓
Chrome Background Tab
        ↓
Timer / CPU Scheduling
        ↓
Measurement Noise ↑

也就是說 Claude Code 操作的 Chrome 分頁,其實一直處於 hidden 狀態,這就產生了一個很危險的問題,我們原本想測的是 Vue Runtime Cost,結果實際上測到的可能變成:

Vue Runtime
      +
Browser Scheduling
      +
Automation Overhead
      +
Background Tab Throttling

環境影響

更關鍵的證據:同一個 Vue,也可以跑出完全不同的數字


完全相同的 Vue 3.5.40 重跑,程式沒改、Scenario 沒改,只改變等待方式(setTimeout vs 忙碌輪詢 microtask vs MutationObserver),得到的 Average Update Duration 從 4.7ms 一路跳到 12ms、48ms、64ms、73ms。

數值 來源與量測情境
4.729 ms 第一輪初期測試 (validation-log.md:L18),使用 btn.click() + 固定 setTimeout(10ms) 驅動時量測到的平均值。
12.188 ms 第一輪初期測試在 Vue 3.6.0-rc.2 下跑出的單次數值(同樣受 setTimeout 節流與背景分頁排程影響)。
48.086 ms / 63.942 ms 改用 MutationObserver 監看 DOM 變化策略重測 Vue 3.5.40 Baseline 時 (validation-log.md:L27-35)的 Trial 2 與 Trial 1 數據。
64ms ~ 73ms 嘗試改用「microtask 忙碌輪詢(busy polling)」等不同等待機制時,因為與 Vue 主執行緒產生 CPU 競爭,以及 Chrome 背景分頁(document.hidden === true)被降頻排程所產生的極端雜訊值。

同一個 Vue 3.5.40 只是改變量測等待方式,結果可以從 4.7 ms 跑到 73 ms 差到 15×,所以推測問題是瀏覽器自動化驅動腳本(setTimeout vs MutationObserver vs Microtask 輪詢)以及背景分頁節流(Timer Throttling / CPU 排程)引入的環境干擾。

經歷這段我們需要修改自動化腳本,以及在 AI 相關文件寫入這次事件發生問題:單次量測不足以支撐版本比較,透過增加 Trial,觀察結果的波動範圍,再用 Median 作為代表值。

所以今天真正被驗證的,是「量測方法」


原本:

Click
  ↓
setTimeout()
  ↓
讀取結果

改成:

Trigger Update
      ↓
DOM Mutation
      ↓
MutationObserver
      ↓
確認 Update 完成
      ↓
讀取 Runtime Metrics

這樣做的目的不是讓數字「看起來比較漂亮」,而是盡量避免 Timer 被 Background Tab 節流。

修正後,再跑一次


這次兩個版本都使用完全相同的 MutationObserver 方法,而且不是只跑一次,每個版本跑 3 次,取 Median。

Metric Vue 3.5.40 Vue 3.6.0-rc.2
# 1 63.942 ms 44.402 ms
# 2 48.086 ms 47.943 ms
# 3 47.042 ms 47.310 ms
Update Duration 48.086 ms 47.310 ms
Computed 10,100 10,100
Watch 100 100
Render 199 199

Vue 3.6 下降 (47.310-48.086)/48.086 = -1.614%,數字看來很好,但是前面提過,當 Vue 3.5 自己重跑,就已經可以出現很大的波動,所以算誤差範圍內。

那 Reactive Chain 到底發生了什麼?


Metric Vue 3.5.40 Vue 3.6.0-rc.2
Update Duration 48.086 ms 47.310 ms
Computed 10,100 10,100
Watch 100 100
WatchEffect 101 101
Render 199 199

DEPTH = 100 各版本連續觸發 100 次 Trigger Update 測試數據顯示,兩邊持平,所以暫時 沒有觀察到可重現、具意義的 Runtime Cost Improvement。

今天真正重要的不是「−1.6%」


如果只看最後一張表,或許會被理解成 Vue 3.5 ≈ Vue 3.6,沒什麼差!

確實沒有證明 Vue 3.6 變快,但是在談 Framework Performance 之前,我們已經可以確定自己量到的值是有價值的,不是測試環境,那 Vue 3.6 到底改善了什麼?我們下一個 Scenario 繼續找……

好的量測方法是成功的開始

參考資料



上一篇
Day 8:Vue 3.5 Baseline - 建立目前 Runtime 行為的觀察基準
下一篇
Day 10:AI Coding 如何避免 Reactive Anti-pattern?
系列文
Vue 演進驗證 × AI Coding 時代的工程實踐12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言