tgoop.com/csharp_gepard/119
Last Update:
Боксинг IEnumerator #скорость #память #бенч
Кажется, что не всем понятна борьба за использование исходной коллекции в .NET. Поясняю весьма избитую истину - бежать по IEnumerable
(IList, IReadOnlyCollection и т.п.) сильно дороже, чем по исходной коллекции. Как по памяти, так и по скорости.
Позволю себе напомнить внутреннюю работу .NET на примере List<T>.
Класс List<T>
обладает методом GetEnumerator
, который вызывается при попытке сделать по нему foreach
. Как можно заметить, List<T>.Enumerator
- структура. Это важно, поскольку структура создаётся на стеке, а её методы вызываются напрямую (см. call и callvirt). Это позволяет пробегать по списку быстро и без затрат на выделение места в куче, а значит без работы GC.
Но стоит нам скастить List<T> к IList<T> - ситуация изменится. В этом случае foreach вызовет метод интерфейса IEnumerable.GetEnumerator
, который возвращает IEnumerator<T>
, то есть интерфейс перечислителя. В случае List’a это будет та же самая структура, но размещённая в куче и доступом к её методам через callvirt. То есть мы не только создадим небольшой memory traffic, но и сильно замедлим перебор коллекции.
Насколько всё это будет медленнее - см. результаты бенчмарка.
BY C# Heppard

Share with your friend now:
tgoop.com/csharp_gepard/119