I frequently hear claims that Reflection in .NET is slow. The discovery of the various metadata element of a type definitely is expensive, but after that cost is incurred, is the invocation of those elements any slower than native code? I’ve often wondered, but never did any tests of my own.
Here is one quick speed test:
SpeedWriter
public class SpeedWriter : IDisposable
{
private readonly Stopwatch _watch = new Stopwatch();
private readonly string _description;
public SpeedWriter(string description)
{
_description = description;
_watch.Start();
}
public void Dispose()
{
_watch.Stop();
long duration = _watch.ElapsedMilliseconds;
Console.WriteLine(string.Format("{0} -- Milliseconds: {1}", _description, duration));
}
}
Foo
Some silly object that I can act upon in my tests
public class Foo
{
public string Bar { get; set; }
public void DoSomething(int x, int y)
{
// do something that the compiler won't optimize away
int sum = x + y;
if ( sum > 1000 )
{
Console.WriteLine("You're exceeded 100!");
}
}
}
DoReflectionTest
private static void DoReflectionTest()
{
Console.WriteLine("--------------- Reflection Test Begin ------------------");
PropertyInfo property = typeof (Foo).GetProperty("Bar");
MethodInfo method = typeof (Foo).GetMethod("DoSomething");
Foo foo = new Foo();
using ( new SpeedWriter("Foo.Bar Setter Test..."))
{
int counter = 0;
while ( counter < 1000 ) // do this a few times
{
property.SetValue(foo, Guid.NewGuid().ToString(), null);
counter++;
}
}
using (new SpeedWriter("Foo.Bar Getter Test..."))
{
int counter = 0;
while (counter < 1000) // do this a few times
{
property.GetValue(foo, null);
counter++;
}
}
using (new SpeedWriter("Foo.Write Method-Invoke Test..."))
{
int counter = 0;
while (counter < 1000) // do this a few times
{
method.Invoke(foo, new object[] { counter, 1 } );
counter++;
}
}
Console.WriteLine("---------------- Reflection Test End -------------------");
}
DoNativeCodeTest
private static void DoNativeCodeTest()
{
Console.WriteLine("--------------- Native Code Test Begin ------------------");
Foo foo = new Foo();
using (new SpeedWriter("Foo.Bar Setter Test..."))
{
int counter = 0;
while (counter < 1000) // do this a few times
{
foo.Bar = Guid.NewGuid().ToString();
counter++;
}
}
using (new SpeedWriter("Foo.Bar Getter Test..."))
{
int counter = 0;
while (counter < 1000) // do this a few times
{
string bar = foo.Bar;
counter++;
}
}
using (new SpeedWriter("Foo.Write Method-Invoke Test..."))
{
int counter = 0;
while (counter < 1000) // do this a few times
{
foo.DoSomething(counter, 1);
counter++;
}
}
Console.WriteLine("---------------- Native Code Test End -------------------");
}
Conclusion
There’s definitely a difference:
I’d like to do some more tests to better understand the difference precisely. I’d also like to create a test case for a dynamic-method implementation to see how close it is to native code.