Перечислить словарь. Вали против самого словаря
Я изучал источники ядра ASP.NET на GitHub, чтобы узнать, какие трюки команда ASP.NET использовала для ускорения работы платформы. Я увидел то, что меня заинтриговало. В исходном коде ServiceProvider в реализации Dispose они перечисляют словарь, и они помещают комментарий, чтобы указать трюк производительности:
private readonly Dictionary<IService, object> _resolvedServices = new Dictionary<IService, object>();
// Code removed for brevity
public void Dispose()
{
// Code removed for brevity
// PERF: We've enumerating the dictionary so that we don't allocate to enumerate.
// .Values allocates a KeyCollection on the heap, enumerating the dictionary allocates
// a struct enumerator
foreach (var entry in _resolvedServices)
{
(entry.Value as IDisposable)?.Dispose();
}
_resolvedServices.Clear();
}
В чем разница, если словарь указан таким образом?
foreach (var entry in _resolvedServices.Values)
{
(entry as IDisposable)?.Dispose();
}
Это влияет на производительность? Или это потому, что выделение ValueCollection будет потреблять больше памяти?
Ответы
Ответ 1
Вы правы, речь идет о потреблении памяти. Разница на самом деле довольно хорошо описана в комментарии: доступ к свойству Value
объекта Dictionary<TKey, TValue>
будет выделять ValueCollection
, который является классом (ссылочный тип), в куче.
foreach
через сам словарь приводит к вызову GetEnumerator()
, который возвращает Enumerator
. Это struct
и будет выделено в стеке, а не в куче.