最初に
この記事はUnity2018.x系の目玉機能を使用するにあたって知っておきたいNativeContainerについての概要を簡単にまとめたものとなります。
NativeContainerって?
C#が提供している安全なContainerとは異なり、アンマネージドなメモリを提供しつつもListやDictionaryのように扱えるContainerのことです。つまりGCでは管理されないので自分でDisposeを行う必要があります。そのため、幾つか守るべきルールとリスクを伴いますが、高速に動作しますし、C# JobSystemにおいてNativeContainerを使用することでメインスレッドとの共有データにアクセスできます(C# JobSystemについては次回の記事で概要を記載します)。
NativeContainerの持つ特徴は以下の4つです。
- Allocator(メモリの割当タイプ)を自身で決める(後述)。
- 使用後はDisposeで開放する必要あり。でないとメモリリークを起こして警告が出る。
- 使えるのは構造体のみ
- 要素数を増やせない
NativeContainer自体はunsafeなC#で書かれているため、新たに自身で[NativeContainer]属性を付加したコンテナを定義することも可能です。ただし通常のNativeContainerは競合が発生した場合は例外発生とログ出力が行われて検出可能ですが、自作コンテナの実装がうまくいっていない場合は(当然ですが)クラッシュする可能性があります。
NativeContainerの種類
配列名 | 概要 |
---|---|
NativeArray<Value> | 通常の配列。 |
NativeSlice<Value> | NativeArrayから一部切り取るのに使用。 |
NativeList<Value> | 追加と削除が容易。List。 |
NativeHashMap<Key, Value> | キーと値のペア。Dictionary。 |
NativeMultiHashMap<Key, Value> | キー毎に複数の値を持つ。複数Dictionary。 |
NativeQueue<Value> | 先入れ先出し(FIFO)の待ち行列。 |
Allocatorのタイプ
Allocatorの種類を設定するタイミングとしては、NativeContainerを実際に作成する時です。
// 引数としては、(要素数, Allocatorの種類)
var a = new NativeArray<MyStruct>(30, Allocator.Persistent);
種類の説明は以下の表の通りです。下に行くほど重くなります。
種類 | 説明 |
---|---|
Allocator.Temp | メモリの割当と開放が最も高速。1フレーム以下での使用を目的としており、スレッドセーフではない。Tempを指定してメモリを確保した場合は関数呼び出しから戻る前にDisposeメソッドを呼び出して開放する。つまりそのフレームのみ有効。 |
Allocator.TempJob | メモリの割当と開放はTempより遅くなる。4フレーム以内での使用を目的としており、スレッドセーフである。4フレーム以内にDispose等で開放を行わないと警告を出力する。ジョブ終了時に自動開放させるオプションが有る。殆どの小規模なJobが、この種類を使用する。 |
Allocator.Persistent | メモリの割当と開放が最も遅いが、アプリの存続期間中、永続的な割当を行う。mallocのラッパー。TempJobを用いるよりも長いJobの場合に使用することがある。使用後はDispose等で開放。パフォーマンスが重要な場所では使用が推奨されない。 |
ReadOnly/WriteOnly属性
NativeContainerフィールドにはReadOnly(読み取り専用)タグ又はWriteOnly(書き込み専用)タグという属性を定義できます。ReadOnlyタグを付与することで複数のJobが並列にデータへアクセスすることが可能になります。
[ReadOnly]
public NativeArray<Vector3> position;
デフォルト(属性なし)の状態だとNativeContainerは読み書きが可能です。そのためメインスレッドから結果を取り出すことが可能です。
最後に
今後の記事でECSとJobSystemについての概要を紹介するつもりですが、その取っ掛かりとして知っておきたいNativeContainerを調べてまとめてみました。私自身は初めてみる機能だったため、調べてみることでJobSystemに入る前の準備ができたような気がします。次はいよいよJobSystemについてざっくり見てみたいと思います。