Обновление:
существует ответ от команды CLR на Microsoft Connect
, Это связано с поисками по словарю в общем коде дженериков. Эвристика во времени выполнения и JIT не работает хорошо на этот конкретный тест. Мы будем смотреть, что может делаться с этим.
Тем временем, Вы можете обходное решение это путем добавления двух фиктивных методов к BaseClass (даже не должны быть названы). Это заставит эвристику работать, как можно было бы ожидать.
Исходный:
Это - сбой JIT.
Может быть зафиксирован этой сумасшедшей вещью:
public class BaseClass<T>
{
private List<T> _list = new List<T>();
public BaseClass()
{
Enumerable.Empty<T>();
// or Enumerable.Repeat(new T(), 10);
// or even new T();
// or foreach (var item in _list) {}
}
public void Run()
{
for (var i = 0; i < 8000000; i++)
{
if (_list.Any())
{
return;
}
}
}
public void Run2()
{
for (var i = 0; i < 8000000; i++)
{
if (_list.Any())
{
return;
}
}
}
public void Run3()
{
for (var i = 0; i < 8000000; i++)
{
if (_list.Any())
{
return;
}
}
}
}
Примечание, что Run2 ()/Run3 () не названы отовсюду. Но если Вы прокомментируете Run2 или методы Run3 то - Вы получите потерю производительности как прежде.
существует что-то связанное с выравниванием стека или с размером таблицы метода, я предполагаю.
P.S. Можно заменить
Enumerable.Empty<T>();
// with
var x = new Func<IEnumerable<T>>(Enumerable.Empty<T>);
все еще та же ошибка.
После некоторого экспериментирования я нашел, что Enumerable.Empty<T>
является всегда медленным, когда T тип класса ; если это - тип значения, это быстрее, но зависит от размера структуры. Я протестировал объект, строку, интервал, PointF, RectangleF, DateTime, Гуид.
Взгляд на то, как это реализовано, я попробовал различные альтернативы и нашел некоторых, который работает быстро.
Enumerable.Empty<T>
полагается на внутренний класс EmptyEnumerable<TElement>
Instance
, статичный свойство .
Затем то, что Enumerable.Empty<T>
действительно делает, является только возвратом пустой массив T.
разные подходы Попытки, я нашел, что замедление вызывается [1 122] и свойство и энергозависимый модификатор.
Принятие статического поля, инициализированного к T [0] вместо Enumerable.Empty<T>
как [1 116]
public static readonly T[] EmptyArray = new T[0];
, проблема исчезла. Обратите внимание, что модификатор только для чтения не является детерминантом. Наличие того же статического поля, объявленного с [1 125] энергозависимый или, получило доступ через , свойство вызывает проблему.
С уважением, Daniele.
Кажется, что существует CLR optimizator проблема. Выключите, "Оптимизируют Код" вкладки Build и пытаются запустить Ваш тест снова.