Chrome 13 では、構造化クローニングというアルゴリズムを使用して、ウェブワーカーとの間で ArrayBuffer
を送受信する機能が導入されました。これにより、postMessage()
API は文字列だけでなく、File
、Blob
、ArrayBuffer
、JSON オブジェクトなどの複雑な型のメッセージを受け入れることができるようになりました。構造化クローニングは、Firefox の新しいバージョンでもサポートされています。
高速化がもたらす利点
構造化クローニングは優れていますが、コピー オペレーションであることに変わりはありません。32 MB の ArrayBuffer
をワーカーに渡すオーバーヘッドは数百ミリ秒になる場合があります。新しいバージョンのブラウザには、Transferable Objects と呼ばれるメッセージ パッシングのパフォーマンスが大幅に改善されています。
転送可能なオブジェクトを使用すると、データがコンテキスト間で転送されます。ゼロコピーであるため、Worker へのデータ送信のパフォーマンスが大幅に向上します。C/C++ の経験がある場合は、参照渡しと考えてください。ただし、参照渡しとは異なり、呼び出し元のコンテキストの「バージョン」は、新しいコンテキストに転送されたら使用できなくなります。たとえば、メインアプリからワーカーに ArrayBuffer
を転送すると、元の ArrayBuffer
は消去され、使用できなくなります。その内容は(文字通り)Worker コンテキストに転送されます。
転送可能オブジェクトを操作するには、転送可能オブジェクトをサポートする新しいバージョンの postMessage()
があります。
worker.postMessage(arrayBuffer, [transferableList]);
window.postMessage(arrayBuffer, targetOrigin, [transferableList]);
ワーカーの場合、最初の引数は ArrayBuffer
メッセージです。2 番目の引数は、転送するアイテムのリストです。この例では、転送可能なリストに arrayBuffer
を指定します。
ベンチマークのデモ
転送可能なアセットのパフォーマンス向上を確認するため、デモを作成しました。
このデモでは、postMessage()
を使用して 32 MB の ArrayBuffer
をワーカーに送信し、ワーカーから返します。ブラウザが transferable をサポートしていない場合、サンプルは構造化クローン作成にフォールバックします。さまざまなブラウザで 5 回実行した結果は次のとおりです。
MacBook Pro/10.6.8/2.53 GHz/Intel Core 2 Duo では、FF が構造化クローンを使用した場合に最も高速でした。32 MB の ArrayBuffer
をワーカーに送信してメインスレッドにポストバックするのに平均 302 ミリ秒(RRT - ラウンドトリップ時間)かかりました。転送可能アセットと比較すると、同じテストで 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 日): ベンダー接頭辞を削除し、コード スニペットを更新しました