転送可能なオブジェクト - 超高速

Chrome 13 では、構造化クローン作成と呼ばれるアルゴリズムを使用して、Web Worker との間で ArrayBuffer を送信できるようになりました。これにより、postMessage() API は単なる文字列ではなく、FileBlobArrayBuffer、JSON オブジェクトなどの複雑な型であるメッセージを受け入れることができるようになりました。構造化クローン作成は、Firefox の新しいバージョンでもサポートされています。

高速化がもたらす利点

構造化クローンの作成は便利ですが、やはりコピー オペレーションです。32 MB の ArrayBuffer を Worker に渡す際のオーバーヘッドは、数百ミリ秒になる可能性があります。新しいバージョンのブラウザでは、転送可能なオブジェクトと呼ばれる、メッセージの受け渡しのパフォーマンスが大幅に向上しています。

転送可能なオブジェクトを使用すると、データはあるコンテキストから別のコンテキストに転送されます。ゼロコピーであるため、Worker へのデータ送信のパフォーマンスが大幅に向上します。C/C++ の世界では、参照パスのようなものと考えてください。ただし、参照によるパスとは異なり、呼び出しコンテキストの「バージョン」は、新しいコンテキストに転送されると使用できなくなります。たとえば、ArrayBuffer をメインアプリから Worker に転送すると、元の ArrayBuffer は消去され、使用できなくなります。その内容が(文字どおり静かに)Worker コンテキストに転送されます。

転送可能なオブジェクトを試すために、転送可能なオブジェクトをサポートする新しいバージョンの postMessage() が用意されています。

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

ワーカーの場合、最初の引数は ArrayBuffer メッセージです。2 つ目の引数は、転送するアイテムのリストです。この例では、転送可能なリストに arrayBuffer を指定します。

ベンチマークのデモ

転送可能な関数によるパフォーマンスの向上を確認するため、デモを作成しました。

このデモでは、postMessage() を使用して 32 MB の ArrayBuffer をワーカーに送信し、戻します。ブラウザが転送をサポートしていない場合、サンプルは構造化クローン作成にフォールバックします。さまざまなブラウザで平均 5 回実行したところ、次の結果が得られました。

構造化クローン作成と移行可能なオブジェクトの比較チャート

MacBook Pro/10.6.8/2.53 GHz/Intel Core 2 Duo では、FF は構造化クローニングを使用した最速でした。32 MB の ArrayBuffer をワーカーに送信してメインスレッドにポストバックするのに平均して 302 ミリ秒を要しました(RRT - Round Trip Time)。転送可能なものと比較すると、同じテストに 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 日): webkitPostMessage() 署名を表示するコード スニペットがウィンドウとワーカーで異なります。更新(2016 年 11 月 3 日): ベンダー プレフィックスを削除し、コード スニペットを更新しました