Unite2017 参加しました その2
パフォーマンス向上のためのスクリプトのベストプラクティス
www.slideshare.net
C# Compiler
- .NET Frameworkはスタック型のマシン
- ソースコードがコンパイルされると最終的に、中間言語(IL)が出力される。
.NET4.6
動画を見直して、再度学習します。 * Unity2017が.NET4.6に対応するので、C#6.0の機能を利用することができる * 非同期処理でAsyncやTasksに対応 * 今後.NET Standard2.0にも対応予定 * .NET4.6が安定したら、新たなGCにも対応よてい
Marshalling
Unmanaged Codeとは
- 開発者自身がオブジェクトやメモリの管理に責任を持つコード。
- GC(Garbage Collector)の対象から外れる。
- DLL/Librarieなどを経由してManaged Codeにアクセスすることができる。
Marshallingとは
- C# やC++ 間で、IntやStringを共有するとき、それぞれのオブジェクトに変換作業。
- Managed codeとUnmanaged Codeを行き来するためのオーバーヘッド作業。
- C#とC++間ではMarshalling asをつけることでClassやStructの対応がとれる。
- Memoaryのレイアウトを意識しないとパフォーマンスに大きな影響を与えてしまう。
- Marshallingするとメモリ内でコピーをしてしまう注意が必要
Unityにおける ManagedHeap
- Heap領域に必要に応じて、メモリを確保する。
- Heap領域が確保できないと、Heap領域を増やす。
- GC(Garbage Collector)は使用されなくなったオブジェクトを削除する。
- GCはHeap領域が足りなくなった場合に、走る。それでも足りないと増やす。
- CGによって削除された空間は、埋められることはないためFragmentのになる。
- そして、一度Heap領域として確保されたメモリは解放されることがない。
避けるためには
- ReuseCollectionを使う。
- 可能な限りStringを避ける。
- ラムダ関数やメソッドはHeapを使ってしまう。
Boxing
- 値型が参照型を引数として渡されるときに発生する。
- 値がheapにallocateされてしまう。(temporary heap managed allocation)
- Fragmentを引き起こす原因になりうる。
Foreachループ
- EnumeratorオブジェクトがHeap領域にAllocateされてしまう。すなわちHeap領域を圧迫してしまう。
- 簡単なForeachであればコンパイラが自動でForloopに置き換える。
- ただし、Collectionの場合はBoxingが発生してしまう。
自身Enumeratorを定義するなど工夫が必要
UnityのAPIでもArrayを返す場合、Heap領域にallocateしてしまう。 ForLoopの中でUnityのArrayを参照する場合は、Loopの前に値をポインタに保持して、そのポインタ経由でアクセスする必要がある。(mesh.verticesやmesh.triangles 遅いのもこれが原因か。)
? Operator
Swiftエンジニアなら慣れ親しんでいるOptional(null許容) C# 6で出てきていたのですね。
参考
[Unite 2016 Tokyo]モバイル端末向けのUnityアプリケーションの最適化実践テクニック - YouTube