ゲームのマスターデータ(変化しないアイテムや敵のパラメータのテーブル)をゲーム中に保持していると、マスターデータのレコード数が増えるとランタイムでのメモリ使用量が気になってくる。
特にレコードに配列やリストをもたせた場合、オーバーヘッドが無視できないので配列やリストのメモリ量を測ってみる。
Unity 2018.2.8fのエディタ上で実行してプロファイラーを使って計測した。.NetのバージョンやAndroid、iPhone、IL2CPP環境では結果が異なるかもしれない。
配列のメモリ使用量
// 40byte
int[] array = new int[0];
// 44byte
int[] array = new int[1];
おそらく配列のオーバーヘッドは40byteでn個のint型配列なら(n * 4 + 40)byteのメモリが確保される。
Listのメモリ使用量
// 32byte
List<int> list = new List<int>();
// 56byte(int[4])
list.Add(0);
Listは内部で配列を持っているので最初にAdd
されたときにデフォルトサイズ4で配列が生成される。
4よりもさらに要素が増えた場合は倍のサイズの配列が確保される。
// 76byte
List<int> list = new List<int>(1);
キャパシティを指定した場合は、そのサイズで配列が生成される。
まとめ
class Record
{
public int[] param = new int[3];
}
// 82.1KB
Record[] array = new Record[1000];
for (int i = 0; i < array.Length; i++)
{
array[i] = new Record();
}
上記のようなレコードを1000個生成しようとした場合、配列のオーバーヘッドだけで40*1000byteとなり、かなりのメモリが消費されてしまうので以下のようにバラバラのメンバーにして保持したほうがメモリ効率はよくなる。
class Record2
{
public int param0;
public int param1;
public int param2;
}
// 35.2KB
Record2[] array = new Record2[1000];
for (int i = 0; i < array.Length; i++)
{
array[i] = new Record();
}
Listを使う場合はキャパシティを設定するほうがメモリ効率がいい。
// 78.2KB
Record2[] array = new Record2[10000];
// 78.2KB
List<Record2> list = new List<Record2>(10000);
レコードを入れるコンテナをリストにするか配列にするかは、リストにキャパシティを指定しているならそこまでメモリに差はない。
参考