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

Chrome 13 では、構造化クローニングというアルゴリズムを使用して、ウェブワーカーとの間で ArrayBuffer を送受信する機能が導入されました。これにより、postMessage() API は文字列だけでなく、FileBlobArrayBuffer、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 日): ベンダー接頭辞を削除し、コード スニペットを更新しました