Performance of Object.GetType()
I doubt you are going to get a satisfying answer from SO on this subject. The reason being that performance, especially scenarios of this type, are highly application specific.
Someone may post back with a quick stopwatch example of which would be faster in terms of raw miliseconds. But frankly that doesn't mean anything for your application. Why? It depends highly on the usage pattern around that particular scenario. For instance ...
- How many types do you have?
- How big are you methods?
- Do you do this for every method, or only big ones?
These are just a few of the questions that will greatly alter the relevance of a straight time benchmark.
The GetType()
function is marked with the special attribute [MethodImpl(MethodImplOptions.InternalCall)]
. This means its method body doesn't contain IL but instead is a hook into the internals of the .NET CLR. In this case, it looks at the binary structure of the object's metadata and constructs a System.Type
object around it.
EDIT: I guess I was wrong about something ...
I said that: "because GetType()
requires a new Object to be build" but it seems this is not correct. Somehow, the CLR caches the Type
and always returns the same object so it doesn't need to build a new Type object.
I'm based on the following test:
Object o1 = new Object();
Type t1 = o1.GetType();
Type t2 = o1.GetType();
if (object.ReferenceEquals(t1,t2))
Console.WriteLine("same reference");
So, I don't expect much gain in your implementation.
I strongly suspect that GetType() will take significantly less time than any actual logging. Of course, there's the possibility that your call to Logger.Log won't do any actual IO... I still suspect the difference will be irrelevant though.
EDIT: Benchmark code is at the bottom. Results:
typeof(Test): 2756ms
TestType (field): 1175ms
test.GetType(): 3734ms
That's calling the method 100 million times - the optimisation gains a couple of seconds or so. I suspect the real logging method will have a lot more work to do, and calling that 100 million times will take a lot longer than 4 seconds in total, even if it doesn't write anything out. (I could be wrong, of course - you'd have to try that yourself.)
In other words, as normal, I'd go with the most readable code rather than micro-optimising.
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
class Test
{
const int Iterations = 100000000;
private static readonly Type TestType = typeof(Test);
static void Main()
{
int total = 0;
// Make sure it's JIT-compiled
Log(typeof(Test));
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
total += Log(typeof(Test));
}
sw.Stop();
Console.WriteLine("typeof(Test): {0}ms", sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
total += Log(TestType);
}
sw.Stop();
Console.WriteLine("TestType (field): {0}ms", sw.ElapsedMilliseconds);
Test test = new Test();
sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
total += Log(test.GetType());
}
sw.Stop();
Console.WriteLine("test.GetType(): {0}ms", sw.ElapsedMilliseconds);
}
// I suspect your real Log method won't be inlined,
// so let's mimic that here
[MethodImpl(MethodImplOptions.NoInlining)]
static int Log(Type type)
{
return 1;
}
}