可移轉物件 - 飛快的執行速度

Chrome 13 引進了使用名為結構化複製的演算法,將 ArrayBuffer 傳送至/傳出網路工作器。如此一來,postMessage() API 就能接受不只是字串的訊息,同時也接受複雜類型,例如 FileBlobArrayBuffer 和 JSON 物件。較新版本的 Firefox 也支援結構化複製功能。

速度越快越好

結構化複製功能固然很好,但還是複製作業。將 32 MB ArrayBuffer 傳遞至工作站的負擔可能多達數百毫秒。新版瀏覽器大幅改善訊息傳遞作業的效能,稱為可轉移的物件

透過可轉移的物件,資料可在內容間轉移至另一個內容。它為零副本,可大幅提升傳送資料給 worker 的效能。如果您是來自 C/C++ 世界,可以將這視為傳遞參考。然而,與即時參照功能不同的是,將呼叫結構定義中的「版本」轉移至新結構定義後,就不再提供使用。舉例來說,將 ArrayBuffer 從主要應用程式轉移至 Worker 時,原始的 ArrayBuffer 會遭到清除,且無法再使用。其內容會 (靜止) 轉移至 Worker 結構定義。

如要使用可轉移的物件,我們推出了新版 postMessage(),支援可轉移的物件:

worker.postMessage(arrayBuffer, [transferableList]);
window.postMessage(arrayBuffer, targetOrigin, [transferableList]);

以 worker 為例,第一個引數為 ArrayBuffer 訊息。第二個引數是應轉移的項目清單。在本例中,您要在可轉移清單中指定 arrayBuffer

基準示範

如要瞭解可轉移項目的成效提升,我們彙整了示範內容。

這項示範使用 postMessage() 將 32 MB ArrayBuffer 傳送至工作站,並返回。如果您的瀏覽器不支援可轉移的資料,範例就會回復為結構化複製。平均來說,每個瀏覽器平均執行 5 次,我得到的結果如下:

結構化複製與可轉移物件比較表

在 MacBook Pro/10.6.8/2.53 GHz/Intel Core 2 Duo 上,FF 使用結構化複製功能最快,平均來說,傳送 32 MB ArrayBuffer 給工作站並回傳至主要執行緒 (RRT - 封包往返時間) 需要 302 毫秒。相較於可轉移的資料,同一次測試需要 6.6 毫秒。效能大幅提升!

擁有這類速度,可讓大量 WebGL 紋理/網格在 worker 和主要應用程式之間流暢傳遞。

特徵偵測

特徵偵測功能在這項功能方面有點困難。建議您傳送小型 ArrayBuffer 給工作站。如已轉移緩衝區但未複製,其 .byteLength 會傳送至 0:

var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);
if (ab.byteLength) {
    alert('Transferables are not supported in your browser!');
} else {
    // Transferables are supported.
}

支援:目前 Chrome 17 以上版本、Firefox、Opera、Safari 和 IE10 以上版本

已更新 (2011-12-13):視窗和 worker 顯示 webkitPostMessage() 簽名的程式碼片段不同。已更新 (2016-11-03):已移除供應商前置字元和更新程式碼片段