Unity のジョブシステムでは、マルチスレッドコードを作成できるため、アプリケーションは利用可能なすべての CPU コアを使用してコードを実行できます。これにより、パフォーマンスが向上します。なぜなら、アプリケーションは 1 つの CPU コアですべてのコードを実行するのではなく、実行中のすべての CPU コアの容量をより効率的に使用するからです。
ジョブシステムを単独で使用することもできますが、パフォーマンスを向上させるためには、Unity のジョブシステム用のジョブをコンパイルするために特別に設計された Burst コンパイラー を使用する必要があります。Burst コンパイラーはコード生成を改善するため、パフォーマンスが向上し、モバイルデバイスでのバッテリー消費が減少します。
また、Unity の Entity Component System でジョブシステムを使用し、高性能なデータ指向コードを作成することもできます。
Unity は独自のネイティブジョブシステムを使用して、独自のネイティブコードを複数の ワーカースレッド で処理します。ワーカースレッドは、アプリケーションが実行されるデバイスで使用可能な CPU コアの数によって異なります。通常、Unity は、プログラムの開始時にデフォルトで実行する メインスレッド と呼ばれる 1 つのスレッドでコードを実行します。ただし、ジョブシステムを使用すると、Unity は複数のワーカースレッドでコードを実行します。これを マルチスレッド と呼びます。
マルチスレッドでは CPU の能力の特性を利用して、複数のコアにわたる多くのスレッドを同時に処理します。タスクや命令を次々に実行するのではなく、同時に実行します。ワーカースレッドは互いに並行して実行され、完了するとその結果をメインスレッドと同期します。
ジョブシステムでは、CPU コアの容量に一致するだけのスレッド数だけが存在することが保証されます。つまり、使用可能な CPU コアの数を具体的に知る必要なく、必要な数のタスクをスケジュールできます。これは、スレッドプール などの手法に依存する他のジョブシステムとは異なります。他のジョブ システムでは、CPU コアよりも多くのスレッドが非効率的に作成されます。
ジョブシステムは、ワーカースレッド間で共有されるタスクの量を均等にするために、スケジューリング戦略の一部としてワークスチールを使用します。あるワーカースレッドは他のスレッドよりも速くタスクを処理する場合があります。あるワーカースレッドがすべてのタスクの処理を終えると、他のワーカースレッドのキューを確認し、別のワーカースレッドに割り当てられたタスクを処理します。
マルチスレッドのコードを書くのを容易にするために、ジョブシステムには安全システムがあり、潜在的な競合状態をすべて検出し、それらが引き起こす可能性のあるバグからユーザーを守ります。競合状態とは、ある処理の出力が、その処理の制御外の別の処理のタイミングに依存する場合に発生します。
例えば、ジョブシステムがメインスレッドのコードからジョブへ、データへの参照を送信する場合、ジョブが書き込むのと同時に、データを読み取っているかどうかを確認することはできません。このシナリオでは、競合状態が発生します。
ジョブシステムは、メインスレッドのデータへの参照ではなく、各ジョブに操作の必要なデータのコピーを送信してこの問題を解決します。このコピーはデータを分離し、競合状態を解消します。
ジョブシステムがデータをコピーする方法は、ジョブが blittable データ型 にしかアクセスできないことを意味します。これらの型は、マネージコードとネイティブコードの間でデータを渡すときに、変換の必要はありません。
ジョブシステムは memcpy を使って blittable 型をコピーし、Unity のマネージ部分とネイティブ部分の間でデータを転送することができます。ジョブのタイミングや順番を決めるときに memcpy を使用してネイティブメモリにデータを格納します。そして、ジョブを実行するときにマネージ側がそのコピーにアクセスできるようにします。詳細については、ジョブのスケジュール を参照してください。
Unity のコアエンジンで提供されるジョブシステムに加えて、Collections パッケージは多くの ジョブタイプ と ネイティブコンテナ を拡張します。詳細については、Collections のドキュメント を参照してください。