Version: 2020.3
分析
マネージメモリ

Unity のメモリ

アプリケーションがパフォーマンス上問題なく動作するためには、Unity がどのようにメモリを使い、割り当てているかを理解することが重要です。このセクションでは、Unity のメモリの仕組みを説明し、アプリケーションのメモリパフォーマンスを向上させる方法の理解を助けることを目的としています。

Unity では、3 つのメモリ管理レイヤーを使用して、アプリケーション内のメモリを処理します。

  • マネージメモリ: マネージヒープと ガベージコレクター を使用する制御されたメモリレイヤー。自動的にメモリ割り当てを行います。
  • C# アンマネージメモリ: Unity Collections 名前空間およびパッケージと組み合わせて使用できる、メモリ管理のレイヤーです。このメモリタイプは、メモリの未使用部分の管理に ガベージコレクター を使用しないため、“アンマネージ” と呼ばれています。
  • ネイティブメモリ: Unity がエンジンを実行するために使用する C++ メモリです。ほとんどの場合、このメモリには Unity ユーザーはアクセスできませんが、アプリケーションパフォーマンスのある面を微調整したい場合には、このメモリを知っておくと便利です。

マネージメモリ

Mono と IL2CPP のスクリプト仮想マシン (VM) は、マネージメモリ システムを実装しています。このシステムは、スクリプトメモリシステムと呼ばれることもあります。これらの VM は、以下の異なるタイプに分けられた制御されたメモリ環境を提供します。

  • マネージヒープ: VM が ガベージコレクター (GC) を使って自動的に管理するメモリのセクションです。このため、マネージヒープ上に割り当てられたメモリは、GC Allocation (GC メモリ割り当て) と呼ばれます。Profiler は、このような割り当ての発生を GC.Alloc サンプルとして記録します。
  • スクリプトスタック: これは、アプリケーションがあらゆるコードスコープに出入りする際に構築され、開放されます。
  • ネイティブ VM メモリ: Unity のスクリプトレイヤーに関連するメモリが含まれています。ほとんどの場合、ネイティブ VM のメモリを操作する必要はありませんが、コードが生成する実行コードに関連するメモリが含まれていることを知っていると便利です。特に、ジェネリック の使用、リフレクション が使用するタイプのメタデータ、VM の実行に必要なメモリが含まれていることを知っていると役に立ちます。

マネージメモリシステムは VM を使用しているため、メモリの割り当ての参照を自動的に追跡し、その生存期間を管理する環境が整っています。つまり、他のコードがメモリにアクセスしようとしているときに、アプリケーションがメモリを解放するタイミングが早すぎる可能性が低いことを意味します。また、コードから、または、使っていないメモリが積み重なってメモリにアクセスできない場合に発生する メモリリーク に対して、ある程度の保護手段があることも意味します。

Unity でマネージメモリを使用することは、アプリケーションのメモリを管理する最も簡単な方法ですが、いくつかのデメリットがあります。ガベージコレクターは便利ですが、メモリの解放と割り当てが予測できないため、動きが途切れる (メモリの解放と割り当てのために、ガベージコレクターが停止しなければならないときに発生) などのパフォーマンス問題につながる可能性があります。この予測不可能な問題を回避するために、C# アンマネージメモリレイヤー を使用することができます。

マネージメモリの仕組みについては、マネージメモリ のドキュメントを参照してください。

C#のアンマネージメモリ

C# のアンマネージメモリレイヤー は、C#コードを書くことによってネイティブメモリレイヤーにアクセスし、メモリ割り当てを微調整することができます。

Unity コア API の Unity.Collections 名前空間 (NativeArray を含む) と Unity Collections パッケージ のデータ構造を使用して、C# のアンマネージメモリにアクセスできます。Unity の C# ジョブシステム、または Burst を使用する場合は、C# アンマネージメモリを使用する必要があります。これについての詳細は、ジョブシステムBurst に関するドキュメントを参照してください。

ネイティブメモリ

Unity エンジンの内部 C/C++ コアは、独自のメモリ管理システムを持っており、これは ネイティブメモリ と呼ばれています。ほとんどの場合、このメモリタイプに直接アクセスしたり変更したりすることはできません。

Unity では、プロジェクト内のシーン、アセット、グラフィックス API、グラフィックスドライバー、サブシステムやプラグインのバッファ、メモリ割り当てなどをネイティブメモリ内に格納しているため、Unity の C# API を通して間接的にネイティブメモリにアクセスすることができます。つまり、Unity のネイティブコアにあるネイティブでパフォーマンスの高いコードのメリットを失うことなく、安全で簡単な方法でアプリケーションのデータを操作することができます。

ほとんどの場合、Unity のネイティブメモリを操作する必要はありませんが、プロファイラープロファイラーマーカー を使えば、アプリケーションのパフォーマンスにどのような影響を与えるかを確認することができます。

分析
マネージメモリ