Performance when creating objects using generic new constraint
I got an email asking about the performance when creating objects using the generic new constraint. You can learn more about the generic new constraint here https://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx and here https://msdn.microsoft.com/en-us/library/d5x73970.aspx. The generic new constraint is used to specify a generic type parameter must implement a default public constructor. You can then create new instances of the generic type in your generic class. Here is the sample from the MSDN documentation.
class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
What happens under the covers though? First lets try a quick performance test. We are going to use the code from the last post. We are going to add an additional test though using the generic new constraint to create the objects. We will create an extremely simple GenericNewFactory class to create the objects. The code for that is below.
public static class GenericNewFactory
{
private static Dictionary<Type, IFactory> _cache = new Dictionary<Type, IFactory>();
public static object CreateObject(Type type)
{
return CreateFactory(type).Create();
}
public static IFactory CreateFactory(Type type)
{
IFactory factory = null;
if (_cache.TryGetValue(type, out factory))
{
return factory;
}
if (type.GetConstructor(Type.EmptyTypes) == null)
{
throw new ArgumentException("type", "The type must have a public default constructor.");
}
Type genericFactoryType = typeof(TestFactory<>).MakeGenericType(type);
factory = Activator.CreateInstance(genericFactoryType) as IFactory;
_cache[type] = factory;
return factory;
}
private class TestFactory<T> : IFactory
where T : class, new()
{
public TestFactory()
{
}
public T Create()
{
return new T();
}
object IFactory.Create()
{
return Create();
}
}
public interface IFactory
{
object Create();
}
}
Lets run the tests and see what happens. I upped the iterations to 10 million. The results are below.
Running 10000000 interations of creation test.
Direct Call 00:00:00.5320932
Delegate Wrapper 00:00:00.8127212
Generic New 00:00:20.2164442
Activator.CreateInstance 00:00:43.3707797
Generic new is faster then Activator.CreateInstance but still way slower then direct call. Let open up our test code in reflector. First thing we notice is new T() is replaced with a call to Activator.CreateInstance<T>(). Why don't we see a newobj call here instead? The newobj instruction has a operand type of InlineMethod and requires the handle for the constructor. I guess the compiler cannot resolve the constructor since the generic type is unknown till jit time maybe?? Why is Activator.CreateInstance<T> faster than Activator.CreateInstance(). I am not really sure. I will try to find out and we will talk about it in another post. Peace :)