ワーカーと並行処理について

Flash Player 11.4 以降、Adobe AIR 13.4 以降(デスクトッププラットフォーム向け)

アプリケーションでワーカーを使用しない場合、実行 スレッド と呼ばれる、1 本の線状の実行ステップブロック内でアプリケーションのコードが実行されます。スレッドは、開発者が記述したコードを実行します。また、スレッドは、ランタイムに含まれるコードの大部分も実行します。その中で特に重要なのが、表示オブジェクトのプロパティが変更されたときに画面を更新するコードです。コードはメソッドやクラスという一定の単位で記述されますが、実行時には、1 本の長い連続したステップとして記述されたかのように一度に 1 行ずつ実行されます。アプリケーションが実行するステップに関する、次のような仮定の例について考察します。

  1. フレーム移動:ランタイムは enterFrame イベントハンドラーを呼び出し、一度に 1 回ずつそのコードを実行します。

  2. マウスイベント:ユーザーがマウスを動かして、様々なロールオーバーおよびロールアウトのイベントが発生するのに応じて、ランタイムがマウスイベントハンドラーを呼び出します。

  3. ロード完了イベント:URL から XML ファイルをロードするリクエストによって、ロード済みのファイルデータが返されます。呼び出されたイベントハンドラーは、XML コンテンツを読み取り、XML データからオブジェクトのセットを作成するというステップを実行します。

  4. マウスイベント:マウスが再度動かされると、ランタイムが関連するマウスイベントハンドラーを呼び出します。

  5. レンダリング:その他の待機中のイベントは存在しないので、ランタイムは表示オブジェクトに対する変更内容に基づいて画面を更新します。

  6. フレーム移動:このサイクルが繰り返されます。

この例で説明したように、仮定のステップ 1 ~ 5 は、フレームと呼ばれる 1 つの時間ブロック内で、順に実行されます。これらのステップが 1 つのスレッドで順に実行されるので、ランタイムは、このプロセスの特定のステップを、別のステップを実行するために中断することはできません。1 秒あたり 30 フレームのフレームレートの場合、これらのすべての処理を実行するためにランタイムに与えられる時間は 1/30 秒未満です。多くの場合、これはコードを実行するために十分な時間であり、残った時間で、ランタイムは単純に待機します。一方、ステップ 3 でロードする XML データが非常に大きく、深い入れ子構造の XML であるとします。この場合、コードでは XML に対するループ処理を実行してオブジェクトを作成するので、その処理を完了するまでに、1/30 秒よりも長い時間がかかる可能性があります。そうなると、その後のステップ(マウスへの反応と画面の再描画)は、想定した時間内に実行されません。そのため、画面がユーザーによるマウスの動作に反応してすぐに再描画されないので、画面がフリーズし、スムーズに進みません。

コード全体を同じスレッドで実行する場合に、ときおりスムーズに進まずフリーズするような状況を避けるための方法は 1 つだけあります。それは、大きなデータセットに対するループ処理などの、長時間持続する処理を実行しないことです。これとは異なる解決策を提供するのが ActionScript ワーカーです。ワーカーを使用すると、長時間持続するコードを個別のワーカー内で実行できます。それぞれのワーカーが個別のスレッドで実行され、バックグラウンドワーカーが独自のスレッド内で長時間持続する処理を実行します。そのため、メインワーカーの実行スレッドが解放され、他の作業によってブロックされることなく、フレームごとに画面を再描画できます。

このようにコードの複数の処理を同時に実行できる機能は、 並行処理 として知られています。バックグラウンドワーカーが自身の作業を完了するか、途中で「進捗」ポイントに達したときに、メインワーカーに通知とデータを送信できます。このようにして、複雑な処理や時間のかかる処理を実行するコードを記述し、一方で画面のフリーズが発生するような粗悪なユーザーエクスペリエンスを防ぐことができます。

レンダリング用のメインスレッドが他のコードによってブロックされることによるフレームレートのドロップの可能性は、ワーカーを使用して軽減できるので便利です。ただし、ワーカーを使用すると追加のシステムメモリおよび CPU の利用が必要になります。そのため、アプリケーション全体のパフォーマンスに対する負荷が増大する可能性があります。それぞれのワーカーは独自のランタイム仮想マシンのインスタンスを使用するので、小さなワーカーであってもオーバーヘッドが大きくなる場合があります。ワーカーを使用する際には、すべてのターゲットプラットフォーム上でコードをテストし、システムに対して過大な要求が課されないことを確認してください。通常のシナリオで使用するバックグラウンドワーカーは、1 ~ 2 個以内とすることをお勧めします。