I'm trying to improve the performance of our application. We have a lot of Activator.CreateInstance calls that are causing some grief.
We instantiate a lot of classes based on an interface (ITabDocument) and after looking around I thought of using this code:
The code is no better (infact marginally slower) than using the Activator.CreateInstance code we had.
public static Func<T> CreateInstance<T>(Type objType) where T : class, new()
{
var dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + objType.Name, objType, null, objType);
ILGenerator ilGen = dynMethod.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, objType.GetConstructor(Type.EmptyTypes));
ilGen.Emit(OpCodes.Ret);
return (Func<T>)dynMethod.CreateDelegate(typeof(Func<T>));
}
I'm wondering why this is, all I'm doing is:
ITabDocument document = CreateInstance<ITabDocument>(Type.GetType("[Company].Something"));
Is there a better way of creating objects which would assist with the above? Its a little hard when you're not sure of the concrete type.
I did some benchmarking between these (I would write down the bare minimum details):
As CD says compiled expression is the fastest, and by a big margin. All the methods except
(T)FormatterServices.GetUninitializedObject(typeof(T))
work only for types with default constructor.And caching the compiled resultant delegate is trivial when you have a static class per generic type. Like:
Note the
new
constraint. Call anythingExcept for the first time the class is being loaded in memory, the execution is going to be fastest.
To have a class that handles both types with default constructor and without, I took a hybrid approach, from here:
Will handle value types too in an efficient manner.
Note that
(T)FormatterServices.GetUninitializedObject(t)
will fail forstring
. Hence special handling for string is in place to return empty string.The problem is if your are going to call CreateInstance over and over again directly rather than saving the result somewhere and using that result over and over again, you should probably just go ahead and do you caching inside of it.
You're probably getting some overhead from the generation of the same code.
The
ILGenerator
dynamically creates code for the factory.Create somekind of map or
Dictionary
of types you've already used, and keep the factory method created for that type.This might help: Don’t use Activator.CreateInstance or ConstructorInfo.Invoke, use compiled lambda expressions:
Generic method for constructing delegates, calling constructor directly. Automatically searches constructor in given type with signature of given delegate type and constructs delegate of that type. Code here:
is part of Yappi project's sources. Using it you can construct delegate calling any constructor of given type, including constructor with parameters (except ref and out parameters).
Sample usage:
After construction of delegate, store it somewhere in static dictionary or in static field of class with generic parameter. Don't construct new delegate each time. Use one delegate for constructing multiple instances of given type.