Субж приводит к вызовам
Activator.CreateInstance, что есть относительно медленно.
Код:
public class Foo<T> where T : new()
{
[MethodImpl(MethodImplOptions.NoInlining)]
public void DoSomething()
{
var obj = new T();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public void DoNothing(){}
}
public class Bar{}
Тест:
public class Program
{
private static void Main()
{
const int N = 1000000;
Thread.CurrentThread.Priority = ThreadPriority.Highest;
var foo = new Foo<Bar>();
var sw = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
{
foo.DoSomething();
foo.DoNothing();
}
sw.Restart();
GC.Collect();
sw.Stop();
sw.Restart();
for (int i = 0; i < N; i++)
{
foo.DoSomething();
}
sw.Stop();
var time = sw.ElapsedTicks;
GC.Collect();
sw.Restart();
for (int i = 0; i < N; i++)
{
foo.DoNothing();
}
sw.Stop();
time -= sw.ElapsedTicks;
Console.WriteLine(time);
Console.ReadKey();
}
}
Минимальное значение после серии запусков — ~288 тысяч тиков.
Немножко меняем:
public class Foo<T> where T : new()
{
private static readonly Func<T> newT;
static Foo()
{
var ctor = typeof(T).GetConstructor(new Type[0]);
var dm = new DynamicMethod("Create", typeof(T), new Type[0], typeof(T), true);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Ret);
newT = (Func<T>)dm.CreateDelegate(typeof(Func<T>));
}
[MethodImpl(MethodImplOptions.NoInlining)]
public void DoSomething()
{
var obj = newT();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public void DoNothing(){}
}
Минимальное значение после серии запусков — ~42 тысячи тиков.
Итого, ускорение почти в 7 раз.
PS Теоретически, такое преобразование могло бы быть сделано компилятором.
PSS На самом деле ожидал большего ускорения...)