tonari note

オンラインゲームエンジニアの雑記

Unityでパフォーマンス稼ぐための小ネタ その1

Unity関係ないといえば無いんですが、今回はLINQメソッドと同じ機能がArrayなりListなりに用意されている場合はそっちのほうが良いときもありますよ、という一例を。

配列を後から持ってくる場合に有効なものです。

using System;
using System.Linq;

class Program
{
	static void Main(string[] args)
	{
		var roopCoount = 10000;
		var start = DateTime.Now;
		var source = Enumerable.Range(0, 100).ToArray();

		start = DateTime.Now;
		for (var roop = 0; roop < roopCoount; ++roop)
		{
			// LINQ Enumerable.Reverse
			source.Reverse().ToArray();
		}
		Console.WriteLine("経過時間 " + (DateTime.Now - start).ToString());
		Console.WriteLine("GC回数 " + GC.CollectionCount(0));

		start = DateTime.Now;
		for (var roop = 0; roop < roopCoount; ++roop)
		{
			// Array.Reverse
			Array.Reverse(source);
		}
		Console.WriteLine("経過時間 " + (DateTime.Now - start).ToString());
		Console.WriteLine("GC回数 " + GC.CollectionCount(0));
	}
}

実行結果

Array.Reverseではインスタンス化が行われないのでGCが行われません。
GC.CollectionCountは開始した時からの累計回数なので、Array.Reverseの方では0回という結果になってます。)
これだけでパフォーマンス結構上がったりします。
まぁLINQの方は毎度ToArrayしてるから当然じゃないか、って感じなんですが結局どこかで評価しなきゃいけないので。

また、

var t = array.Where().Reverse().ToArray();

よりも

var t = array.Where().ToArray();
Array.Reverse(t);

のほうがパフォーマンスが良いです。
実行結果

僕はリアルタイムな読み込みでバイナリを変換する時にエンディアンが違って逆転が必要になった、というパターンのときに使ったりしました。