63
задан 30 November 2014 в 15:55

3 ответа

Обновление:
существует ответ от команды 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>);

все еще та же ошибка.

31
ответ дан 31 October 2019 в 13:00

После некоторого экспериментирования я нашел, что 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.

0
ответ дан 31 October 2019 в 13:00

Кажется, что существует CLR optimizator проблема. Выключите, "Оптимизируют Код" вкладки Build и пытаются запустить Ваш тест снова.

-2
ответ дан 31 October 2019 в 13:00

Другие вопросы по тегам:

Похожие вопросы: