當我們把像素或大型二進位從主緒丟到 Web Worker,真正決定體驗的不是演算法本身,而是資料怎麼過邊界。瀏覽器有三條路:Structured Clone(預設)、Transferable、SharedArrayBuffer(SAB)。它們像三種搬家方式:複製一份、把房契過戶、乾脆住同一棟。
Structured Clone最省心:postMessage(obj)
什麼都能傳,但會複製。對 4K 影像,這等於每次多做一份拷貝;方便,但慢。
Transferable是把 ArrayBuffer
的「所有權」直接交給對方:
worker.postMessage(bytes.buffer, [bytes.buffer]) // 轉移所有權
幾乎零拷貝,速度最佳,但原端 buffer 會變成「detached」。對影像工作流來說,這通常是對的選擇;唯一要注意的是別轉移 canvas 的底層 buffer,否則主緒後續寫回畫布會爆(先複製一份獨立的 Uint8Array 再轉移)。
SharedArrayBuffer讓雙方共享同一塊記憶體,配合 Atomics
可做鎖與訊號。理論上最靈活,但門檻高:必須開 COOP/COEP、CDN/站點得正確送出 header,Safari 兼容性也要考慮。對我們這種「提交任務、等結果」的影像管線,多半不必上 SAB;Transferable 已夠快且心智負擔更低。
實務建議:主緒取出 ImageData
→ 複製一份新的 Uint8Array(避免碰到 canvas 的內部記憶體)→ 用 Transferable 丟進 Worker;Worker 內部再把這塊交給 WASM。需要多工就用 Worker Pool,每個任務各帶自己的 buffer,避免共享造成的資料競爭。除非你需要持續流式處理與細粒度同步,否則別急著用 SAB。