WASM linear memory 是 GC 管不到的記憶體
WASM heap(線性記憶體)就是一塊連續的 bytes,從 JS 看過去是一個巨大的
ArrayBuffer。C 程式碼裡的「位址 0x1000」在 JS 這邊就是HEAPU8[0x1000]——指標其實只是這個 buffer 的索引。
對照 JS heap
| JS heap | WASM heap | |
|---|---|---|
| 誰管 | V8 的 GC 自動回收 | C 程式碼自己 malloc / free |
| 結構 | 物件圖,有 header、hidden class | 一整塊連續 bytes |
| 怎麼變小 | GC 跑過就回收 | 只有 free() 會還,整塊配額通常不縮回去 |
WebAssembly.Memory 只有 grow() 沒有 shrink()——向瀏覽器要過的空間就不會還。庫內部 free 掉的空間會被它自己重複利用,但整塊不縮。
兩個實務後果
- 必須顯式關閉:JS 的 GC 只會回收那個指向 WASM memory 的包裝物件,碰不到裡面的資料。所以像 sql.js 這種函式庫,重新載入前一定要先
db.close(),否則每次都疊加一份完整資料,是穩定洩漏。 - devtools 的數字不會降:載入後記憶體居高不下是正常的,不代表洩漏。
硬上限
wasm32 的位址是 32-bit 整數,2^32 = 4GB——這是規格層級的天花板,不是瀏覽器政策(memory64 提案尚未普及)。實務上還會先撞到單一 ArrayBuffer 的上限(Chrome 約 2GB)與 Worker 與分頁共用同一份記憶體配額。