Posted at

C# のリフレクションを使うとどれだけ遅くなるのか

More than 1 year has passed since last update.

遅いと言われがちなリフレクションの処理時間を調べました。

今回は比較対象は同じ処理ではありません。似たような状況があったのでそれを想定して比較しています。

リフレクションを使う場合はあるインタフェースを実装しているクラス全てを探して実体化し処理をさせます。

リフレクションでない場合は対象のクラスをあらかじめ全て記述しておくという回避策を取ります。

この両者を比較しました。


コード

using System;

using System.Diagnostics;
using System.Linq;
using System.Reflection;

namespace PlayGround
{
using MyReflection;

class Program
{
static void Main(string[] args)
{
var sw = new Stopwatch();
var N = 1;

sw.Restart();
// Reflection
for (var i = 0; i < N; i++)
{
var str = "";
// MyReflection名前空間のNameGettableを実装しているクラスすべてを取る
var instances = from type in Assembly.GetExecutingAssembly().GetTypes()
where type.Namespace == nameof(MyReflection) && type.IsClass && type.GetInterfaces().Contains(typeof(NameGettable))
select Activator.CreateInstance(type) as NameGettable;
foreach (var instance in instances)
{
str = instance.Name; // なにかさせる
}
}
Console.WriteLine(sw.Elapsed);

sw.Restart();
// not Reflection
for (var i = 0; i < N; i++)
{
var str = "";
var instances = new NameGettable[] { new HogeA(), new HogeB() };
foreach (var instance in instances)
{
str = instance.Name; // なにかさせる
}
}
Console.WriteLine(sw.Elapsed);

Console.Read();
}
}
}

namespace MyReflection
{
interface NameGettable
{
string Name { get; }
}

class HogeA : NameGettable
{
public string Name { get { return nameof(HogeA); } }
}

class HogeB : NameGettable
{
public string Name { get { return nameof(HogeB); } }
}
}


結果

// N=1

00:00:00.0010076
00:00:00.0000184

// N=1000000
00:00:03.1758372
00:00:00.0479427

リフレクションは100万回回して3.1s、かたやリフレクションじゃない方はミリ秒台にも乗らず。

一回しか使わないならいいですが、ループになる場所で使うには気をつけたいです。

言っても秒のオーダーなのでそこまで処理速度がシビアでない場合は全然許容できます。