パフォーマンス
データフローで値の受け渡しをする場合、ボックス化でのGC Allocなどによりパフォーマンスが低下する恐れがあります。
ボックス化の発生条件
以下のいずれかに該当する場合にボックス化が発生します。
- ValueMediatorに登録されていない値型を受け渡している。
- 値型の入出力にobject版入出力メソッドを使用している。
- Reflectionなどでobject型を介すメンバーを使用している。
- DataLinkAttributeを利用して値型フィールドへ直接入力している。
- 以下の組み込みスクリプトを使用している場合、object型を直接取り扱っているためボックス化の回避不可
ボックス化回避方法
型固有のスロットクラスを使用する
例えばint型のみの使用が確定している場合にはOutputSlotIntを使用するなど、不必要な汎用タイプのスロット使用は避けてください。
ValueMediatorによるボックス化回避
OutputSlotAnyやOutputSlotTypableなどを使用する場合、ValueMediatorを使用することでボックス化が削減できます。
ただし、ValueMediatorを利用した場合でも初回出力時は格納用インスタンス生成のためにGC Allocが発生します。
2回目以降の出力の際に、作成しておいた格納用インスタンスを使いまわすようにすることで、ボックス化を回避しています。
ValueMediatorの登録
ValueMediatorに値型を登録しておくことで、ボックス化が削減できます。
- ValueMediatorInitializeOnLoadMethod
staticメソッドにValueMediatorInitializeOnLoadMethod属性を付けるとValueMediatorが初期化される際に呼ばれるようになります。 - ValueMediator.Register
値型をValueMediatorに登録します。
例として、Arbor.Example名前空間にあるDataFlowExampleData構造体をValueMediatorに登録するコードは以下のようになります。
|
|
予め登録済みの型
- sbyte
- byte
- short
- ushort
- int
- uint
- long
- ulong
- char
- float
- double
- decimal
- UnityEngine.Vector2
- UnityEngine.Vector3
- UnityEngine.Vector4
- UnityEngine.Quaternion
- UnityEngine.Rect
- UnityEngine.Bounds
- UnityEngine.Color
- UnityEngine.Color32
- UnityEngine.Matrix4x4
- UnityEngine.Vector2Int
- UnityEngine.Vector3Int
- UnityEngine.RectInt
- UnityEngine.BoundsInt
値の入出力にジェネリック版メソッドを使用する
OutputSlotAny.SetValue(object)などのobject版メソッドを使用するとその時点でボックス化してしまうため、代わりにSetValue<T>(T value)などのジェネリックメソッドを使用してください。
出力スロット側の例
|
|
入力スロット側の例
|
|
Reflectionを利用しない
DataLinkAttributeやInvokeMethodスクリプトなどは便利な反面、Reflectionを介すためボックス化が発生します。
FlexibleField系から入力するようにしたり、固有メソッド呼び出しなどのスクリプトを自作してください。