Transferable オブジェクト
コピーせずにデータを効率よく移動します。
「Transferable オブジェクト」はCoddyKit上の無料JavaScript Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJavaScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 JavaScript Academyコースには全4レッスンが含まれています。
複製のコスト
構造化複製では、データを1バイトずつコピーします。大きなバッファー(画像、音声、大きな配列)では、このコピーに時間がかかり、メモリ使用量も倍増します。転送可能オブジェクトを使えば、コピーする代わりに所有権を移動してこの問題を解決できます。
転送できるもの
転送できるオブジェクトの型は限られており、最も重要なのはArrayBufferです。そのほかにMessagePort、ImageBitmap、OffscreenCanvasなどがあります。
ArrayBuffer— 生のバイナリメモリMessagePort— チャネルのエンドポイントImageBitmap— デコード済みの画像データ
転送リスト
postMessageは第2引数として、転送可能オブジェクトのリストを受け取ります。そのリストに含まれるオブジェクトはコピーされず、移動されます。
const buffer = new ArrayBuffer(1024 * 1024); // 1 MB
worker.postMessage(buffer, [buffer]); // transfer it所有権の移動
転送後、送信側はそのバッファーを使用できなくなり、切り離された状態になります(byteLength 0)。受信側が同じ基盤メモリの所有権を持つため、コピーは行われません。
const buffer = new ArrayBuffer(8);
worker.postMessage(buffer, [buffer]);
console.log(buffer.byteLength); // 0 - now detached型付き配列を転送する
型付き配列の基盤となるArrayBufferは、その.bufferプロパティを介して転送します。ビュー自体は転送できませんが、そのバッファーは転送できます。
const data = new Float64Array(100000);
worker.postMessage(data, [data.buffer]);
// data is now detached on this side.転送されたデータを受信する
受信側では、複製されたメッセージとまったく同じように、転送されたオブジェクトをevent.dataから読み取ります。違いは、コピーが行われていないことだけです。
// worker.js
self.onmessage = (e) => {
const buffer = e.data; // we now own this memory
const view = new Uint8Array(buffer);
view[0] = 255;
};結果を送り返す
処理後、ワーカーはバッファーを再びコピーなしで転送して、所有権をメインスレッドに戻すことができます。
// worker.js
self.onmessage = (e) => {
const buffer = e.data;
// ...process the bytes...
self.postMessage(buffer, [buffer]); // transfer back
};転送と複製のパフォーマンス
数キロバイト程度であれば、違いは無視できるほど小さいものです。バイナリデータが数メガバイトになると、転送の方が大幅に高速で、メモリ使用量の急増も避けられます。大きなバッファーには転送を使用しましょう。
転送後の使用によるバグを避ける
よくある間違いは、転送した後にバッファーを読み取ることです。バッファーが転送リストに現れた時点で、すでに使えなくなったものとして扱ってください。
worker.postMessage(buffer, [buffer]);
// BUG: buffer is detached here; this reads zero length.
// const len = buffer.byteLength; // 0複製データと転送データを組み合わせる
バッファーを含むオブジェクトを送信し、そのバッファーだけを転送できます。オブジェクトは複製され、リストに指定したバッファーは移動されます。
const msg = { type: 'frame', pixels: buffer };
worker.postMessage(msg, [buffer]);
// msg.type is cloned; buffer is transferred.転送を使う場面
画像、音声、動画の処理、大規模な数値計算、スレッド間で大きなバイナリデータを移動するパイプラインには、転送可能オブジェクトを使用します。小さなJSON形式のデータには、通常の複製の方がシンプルで十分です。
確認問題
転送可能オブジェクトについての理解度を確認しましょう。
まとめ
転送可能オブジェクトについて学びました。
postMessageの第2引数として転送リストを渡します。ArrayBuffer(および一部のほかのオブジェクト)はコピーではなく移動されます。- 転送後、送信側のバッファーは切り離された状態になります。
- 型付き配列は
.bufferを介して転送します。 - 大きなバイナリデータには転送を使い、小さなデータには複製を使います。
次は、ワーカーの用途と制限について学びます。
よくある質問
「Transferable オブジェクト」レッスンは無料ですか?
はい。「Transferable オブジェクト」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、JavaScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 JavaScript Academyコースには全4レッスンが含まれています。
「Transferable オブジェクト」で何を学びますか?
コピーせずにデータを効率よく移動します。 ブラウザで直接実行するハンズオンコードでJavaScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
JavaScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJavaScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「Transferable オブジェクト」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJavaScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのJavaScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Web Worker を作成する
- postMessage でメッセージを送る
- Transferable オブジェクト
- 活用例と制限事項