SerializeReferenceアトリビュートを付けた参照とScriptableObjectの参照の読み込みはどちらが高速なのか検証してみました。
実験に使用したクラスは以下の通りです。
class A1 : ScriptableObject { public A2[] Children; } class A2 : ScriptableObject { public Matrix4x4 Matrix; } class B1 : ScriptableObject { [SerializeReference] public B2[] Children; } [Serializable] class B2 { public Matrix4x4 Matrix; }
A1(B1) の Children には A2(B2) のインスタンスが100個入っています。 A1(B1) をアセットバンドル化し、Load / Unload を10000回行いました。
環境は 2020.3.25f1 Win64 IL2CPP で下が計測結果になります。
Overview | GC Alloc (A) | GC Alloc (B) | Time (A) | Time (B) |
---|---|---|---|---|
AssetBundle.LoadFromFile | 2417.20 | 1619.79 | ||
File.Open | 710.61 | 596.70 | ||
File.Read | 402.12 | 366.84 | ||
File.Close | 244.46 | 220.33 | ||
Loading.LoadFileHeaders | 139.12 | 118.60 | ||
AssetBundle.LoadBundleObject | 17.02 | 15.25 | ||
Loading.MemoryFileSystemOpen | 40.10 | 39.46 | ||
File.Seek | 27.60 | 27.07 | ||
Loading.MemoryFileSystemClose | 12.45 | 12.25 | ||
Loading.MemoryFileSystemRead | 10.19 | 9.16 | ||
Loading.MemoryFileSystemWrite | 9.14 | 8.48 | ||
Loading.ArchiveFileSystemMount | 7.52 | 7.12 | ||
Loading.AwakeFromLoad | 0.62 | 0.59 | ||
Loading.MemoryFileSystemSize | 0.55 | 0.55 | ||
LoadObjectsThreaded | 62.00 | 10.47 | ||
Loading.ReadObjectThreaded | 2512.57 | 945.16 | ||
GC.Alloc | 92.2MB | 84.5MB | 47.17 | 44.04 |
GC.Collect | 92.2MB | 84.5MB | 307.69 | 25.51 |
AwakeFromLoadThreaded | 31.23 | 1.44 | ||
AsyncReadManager.SyncRequest | 4.41 | 3.06 | ||
Loading.FindInThreadedActivationQueue | 103.69 | 0.95 | ||
APIUpdaterRuntimeHelpers.GetMovedFromAttributeDataForType | 9.0KB | 0.93 | ||
GC.Resize | 0.00 | 0.00 | ||
IntegrateAllThreadedObjects | 246.30 | 39.10 | ||
Loading.ArchiveFileSystemClose | 8.01 | 6.86 | ||
Loading.MemoryFileSystemClose | 7.61 | 7.05 | ||
Loading.LoadRemainingPreallocatedObjects | 8.97 | 2.96 | ||
Loading.MakeObjectUnpersistent | 1.77 | 1.55 | ||
GC.Alloc | 234.4KB | 234.4KB | 1.53 | 1.27 |
合計 | 7381.65 | 4132.54 |
SerializeReferenceを使用した場合だけAPIUpdaterRuntimeHelperのメソッドが呼ばれていました。実装を見るとMovedFromアトリビュート用の処理のようです。
構造によって変わってくる部分があるかもしれませんが、今回のテストではSerializeReferenceを使用した方が速いという結果になりました。ScriptableObjectを大量に含むアセットを作る場合はSerializeReferenceを利用しても良さそうです。