where T: new()
От: artelk  
Дата: 30.10.14 23:34
Оценка:
Субж приводит к вызовам 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 На самом деле ожидал большего ускорения...)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.