Optimising the generic new T()

Topics: C# Language Design
Apr 9, 2014 at 5:38 PM
Would it be possible to optimise the way the compiler handles new T() ?

I recently learned that this translates to Activator.CreateInstance() when I had always assumed it just compiled down to a call to the default constructor call.

Is there something neat you can do with the new compiler framework to make new T() do the obvious and just call the default constructor?
Coordinator
Apr 10, 2014 at 5:53 PM
The ".ctor" constraint (CLR representation of "new" constraint) tells only that any type that satisfies that constraint would be creatable via "new T()" - i.e. it has a public parameterless constructor or it is a struct. However the actual constructor method cannot be known at compile time and regular way of instantiation - "newobj <.ctor token>" requires compiler to specify precisely which constructor to call. As a result, the only way out is to defer generic instantiation to a runtime helper.

Note that even if a special IL instruction would be introduced for this purpose, the runtime behavior of such instruction would be generally too complex to be emitted directly into machine code of the method. Instead JIT would emit a call to some helper with behavior very much like Activator.CreateInstance(), thus considerably diminishing the value of providing a special instruction over just providing a special helper.
Apr 13, 2014 at 10:17 AM
Edited Apr 13, 2014 at 10:18 AM
How much slower is Activator.CreateInstance() compared to invoking a parameterless constructor directly, anyway? Have you measured it, dgkimpton?
Apr 13, 2014 at 11:46 AM
How much slower is Activator.CreateInstance() compared to invoking a parameterless constructor directly
It's 20-30x slower. For example on a Corei7 CPU @ 2.50GHz it takes 85ms to create 1 million objects with "new T()" and only 3ms if you invoke the constructor directly. Of course, not everyone is using "new T()" to create 1 million objects. If you create only a handful of objects it's unlikely you'll notice any difference, even the slow new T() takes less than 100ns to create an object.

If you have a scenario where performance matters one alternative is to not use "new T()" but instead use a delegate that takes care of object creation. This is almost as fast a using "new Foo()":
void CreateObjects<T>(Func<T> create)  {
    for (int i = 0; i < 1000000; i++)
        create();
}
... 
CreateObjects(() => new Foo());