なんとかするから、なんとかなる

エンジニア関係のことを書きます

Unite2017 参加しました その2

パフォーマンス向上のためのスクリプトのベストプラクティス

www.slideshare.net

C# Compiler

.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

Unity - Manual: Understanding the managed heap

.NETの中間言語 | C#たんっ!