Javascriptの重い処理はWeb Workerに任せよう

Web Workerを使用することで負荷の大きな計算処理をWorker Thread(ワーカースレッド)で実行することができます。これによりMain Thread(メインスレッド)を空き状態にすることができるため、ブラウザのパフォーマンスが向上します。
この記事ではWeb Workerの仕組みと使い方をご説明します。

Web Workerって何?

ブラウザでは主にMain Thread(メインスレッド)、Worker Thread(ワーカースレッド)、Raster Thread(ラスタースレッド)、Compositor Thread(コンポジタースレッド)の4種類のスレッドがそれぞれ割り当てられた処理を実行しています。その中でもメインスレッドが一番忙しく、Javascriptの計算やスタイルの計算は基本的にはすべてメインスレッドで実行されます。

Main Threadばかりを酷使
Main Threadばかりを酷使するとその分時間がかかり、画面のフレームレートが低下してしまいます。

一方、Worker Thread(ワーカースレッド)は基本的に暇にしています。Main Threadから仕事の依頼があった時のみ働きますが、自発的に働くことはありません。あくまで、Main Threadから仕事の依頼があった場合のみ、真面目に働いてくれます。このようにWeb Workerをうまく使うことによってMain Threadになるべく負荷のかからないようにしておくことができます。

メインスレッドが忙しくなるとどうなるの?

メインスレッドが常にタスクを処理している状態になると、次のような不具合に見舞われます。

アニメーションやスクロールの描写がカク付きユーザービリティーが低下します。

画面の更新は基本的に60fps(16msに一回の頻度)を保つと最適と言われていますが、メインスレッドが忙しくなると60fpsを保つ事ができなくなり、画面がなめらかに動かなくなります。

クリックなどのユーザーインタラクションに待ちが発生する。

メインスレッドがユーザーからの入力を受け取った時に他の処理に追われていると、その処理が完了するまでユーザーにレスポンスを返すことができず、待たせてしまうことになります。

Web Workerを使用した場合の効果

Web Workerの効果を画面上で確認するためのデモを作成しました。

部品の説明

Timer 100ms毎に1ずつカウントアップします。
Run with Workers 1~999999999までをWeb Workerを使用して足し合わせます。
Run without Workers 1~999999999までをWeb Workerを使用しないで(Main Thread上で)足し合わせます。

See the Pen
Web Workers
by Jonny Gerig Meyer (@jgerigmeyer)
on CodePen.

結果

Web Workerを使わなかった場合
『Run without Workers』を押したタイミングでTimerのカウントが一時停止します。これはメインスレッドが計算処理に時間を取られ、他の処理を待たせていることを表しています。

Web Workerを使った場合
『Run with Workers』を押してもTimerが一時停止することはありません。Timerのカウントアップは継続して行われ、Worker Threadが計算を完了した時点で結果が表示されていることが確認できます。このようにWorker Threadをうまく使うことでユーザビリティーの向上が期待できます。

Web Workerの実装方法

基本的にWeb Workerを利用する場合、まずWeb Worker実行用のjsファイルを作成します。
Main ThreadとWorker Threadのやり取りはself.addEventListener('message'を介して行われます。

Web Workerの注意点
Worker ThreadからはDOMにアクセス出来ないため、気をつけましょう。

Web Workerを使用するケース

Worker ThreadからはDOMにアクセスできないため、基本的には演算(数値計算)処理を任すことが多くなるかと思います。主なケースとしてはCanvasを用いる場合に大変有用です。以下のデモはCanvas上に表示する模様の計算をWeb Workerで行っています。

Canvas上に表示する模様の計算をWeb Workerで実施
Web Worker使用例
Canvas上で表示している模様の計算をWeb Workerで行っています。

Codepenで見る

まとめ

Web Workerを使ってバックグラウンドで処理ができるので、大量の計算が発生する場合は大変有用です。また、canvasを使った描写計算がある場合は積極的に使ってみてください。

関連記事

レンダリングのパフォーマンス対策入門〜アニメーション、JSで困った時に

最新記事