Chrome 13 では、構造化クローン作成と呼ばれるアルゴリズムを使用して、Web Worker との間で ArrayBuffer
を送信できるようになりました。これにより、postMessage()
API は単なる文字列ではなく、File
、Blob
、ArrayBuffer
、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 日): ベンダー プレフィックスを削除し、コード スニペットを更新しました