Edit: As a result of these tests, I’ve written a better-performing set of extension methods.
I recently wrote an extension method
which uses an Expression Tree to create a
Func which creates an instance of an object from its type.
With that done I thought I’d check the performance difference between my method and
Activator.CreateInstance(), which it was intended to replace.
I wrote a simple console application which tested using
Activator.CreateInstance() by creating 100,000 instances of objects with zero to three constructor
parameters and calculating the average time of each construction. For
Activator.CreateInstance() I created a single instance of each object before running the test
so they could perform any caching outside of the actual performance measurement.
The results were as follows; the third column shows the total number of ticks taken to create 100,000 objects, the fourth the number of ticks taken per object:
A few things to note:
newis always and by far the fastest way to go.
With a parameterless constructor, using
Activator.CreateInstance()is almost as fast as using
new, and much, much faster than using
When your constructor takes one or more parameters,
Type.GetInstance()takes about 70% the time of
I find myself wondering why
Type.GetInstance() isn’t faster than it is; after all, aren’t
created by Expression Trees supposed to nearly as fast as regular code? I’ve not looked into it in
any great detail, but I think its performance is weighed down by the generic nature of the method
and the way the
Funcs are cached.
Funcs are cached in a dictionary which returns a
Func<object, object, object, object>,
Func requires an Expression to cast each argument to its correct type, and this introduces
overhead. This is confirmed by looking at the Expression Debug View in Visual Studio, which displays
the created Lambda like this:
With these results, I’m going to update the parameterless overload of
Type.GetInstance() to delegate
Activator.CreateInstance(), and I wonder if I might be able to use a generic helper class
to cache a strongly-typed
Func and so avoid the casting… something to consider (I’ve now considered
it and written new methods).
I guess it’s always best to make decisions based on data :)