Workersがこんなに遅いわけがないらくさん2013.12.02フロントエンジニアフロントエンドエンジニアのらくさんです。2日目の記事になります。Workersというものがありますが、Androidの標準ブラウザでは使えないためスマートフォン向けには使いにくい状況が続いていました。30ベースのものになり、標準ブラウザはどうなるのかまだ不透明ではありますが、標準ブラウザとしてChromeをプリインストールするかChromiumベースのものになっていく流れだと思われます。Workersが使える機会が徐々に増えていくでしょう。Workersを使っています。Objectsについてまとめました。Workersって何だっけ?という人以外は読み飛ばしてもらって構いません)。JavaScriptという言語は、すべての処理が単一スレッドで動作するようにできています。setTimeoutで実行される処理やXMLHttpRequestのコールバックなど、非同期で動作するものはたくさんありますが、これらも全て単一のスレッドで動作します。setTimeoutで実行される処理に時間がかかりすぎると、その間は他の処理が全て止まってしまいブラウザが固まったりするわけです。そんなJavaScriptにマルチスレッドプログラミングをもたらすのがWebWorkersです。いうJavaScriptファイルを実行するワーカーを作り、3行目でそのワーカーからデータを受け取るイベントハンドラを設定、6行目でワーカーにメッセージを送信しています。受け取ったメッセージを小文字にして送り返しているだけです。world!」と小文字でアラートが表示されます。関数を介して行う必要があります。アクセスすることはできません。dataself.postMessage(lower);};[/sourcecode]また、ワーカー内ではDOMの操作はできません。他にもできないことがいくつかありますが、ここではそれらについて触れません。Objectsを利用できる環境かどうかを判定するまとめ大きなデータを受け渡すメインスクリプトとワーカーの間でデータを受け渡す際、オブジェクトの参照が渡されて共有されるのではなく、コピーされて渡されます。さきほどの例で受け渡されるデータはとても小さく、データがコピーされることによるオーバーヘッドを気にするようなものではありません。大きなデータを受け渡したい場合はどうでしょうか。次のコードは、32MBのUint8Arrayを作りメインスクリプトとワーカーの間で1往復の受け渡しをし、その時間を計測しています。{self.postMessage(event.data);};[/sourcecode]私のiPhone5sでは150ms前後、iPhone5(iOS6)では200ms前後でした。Objects150ms程度だと、一度だけワーカーに渡せばよい場合はそれほど問題ではないかもしれませんが、繰り返し受け渡す場合は十分な速さとはいえません。そこで、コードを次のように修正します。2つ目の引数を追加しています。この修正により2ms程度になりました。2つ目の引数が、今回の記事のメインテーマです。次のように書かれており、2つ目の引数にTransferableの配列を渡すことができることがわかります。transfer);Transferableの仕様はここに書かれています。2つ目の引数に列挙することで、コピーを伴わずに転送することができます。なんでもコピー無しで転送できるわけではありません。ワーカーに渡しました。自身はコピーされます)。コピー無しで転送できます。文字列はコピーされます。data.f32.buffer]);[/sourcecode]CanvasのImageDataCanvasのImageDataのデータ領域もArrayBufferのため、コピー無しでワーカーに転送できます。大量のピクセル操作を行う場合にとても有用です。[imageData.data.buffer]);[/sourcecode]ちなみに、CanvasとWorker関連ではCanvasProxyという仕様が策定中です。ImageDataの転送ではピクセル単位の操作しかできませんが、CanvasProxyによりWorker内でCanvasの機能が使えるようになります。&quot;red&quot;;context.fillRect(...);};[/sourcecode]転送後のTransferableなオブジェクトは転送元でどうなる?転送後のTransferableなオブジェクトは転送元ではアクセスできなくなります。null[/sourcecode](Safariではdata.bufferは転送後にnullになりますが、Chromeではnullになりませんでした。data.lengthは0になっており、データの内容にはアクセスできないことに変わりありません。Objectsを利用できない環境でpostMessageの2つ目の引数を指定してもコピーを伴って送信されます。その場合、前述のdata.lengthは0にならずにもとの長さのままです。Objectsを利用できる環境かどうか判定することができます。Objectsを使ってワーカーとのデータ受け渡しを高速化する方法をまとめました。Objectsを使えるようにデータ構造を設計することで大きな効果が期待できます。Workersの利用を検討してみると良いでしょう。SHARE記事作成者の紹介らくさんフロントエンジニアフロントエンドエンジニアのらくさんです。JswfPlayerという弊社サービスでFlash再生エンジンを開発したり、動画広告Guileの動画プレーヤーを開発したりしています。公式XWeb制作・アプリ開発に関する、UI/UX情報、エンジニア向け情報、イラストテクニックをお届けしています。