Ответ 1
Тест производительности для контейнеров IoC от
Дэниел Пальме (но и другие) немного вводит в заблуждение, поскольку эталонный анализ разрешает очень мелкие графические объекты из контейнера (хотя он явно показывает, что различия в производительности между контейнерами являются большими). Это нереально, потому что большинство приложений (которые используют DI правильно) будут иметь графы объектов, которые содержат досы объектов. При этом разрешается разрешать только корневой объект, и когда контейнер правильно написан, это означает, что в большинстве ситуаций (или, самое большее, несколько) вы будете иметь только один вызов Dictionary<T,V>.TryGetValue
per (web) запроса, Из-за этого производительность Dictionary<T, V>
не является проблемой.
Я полагаю, что большая часть затрат на производительность Dictionary<T,V>
, где TKey
равна System.Type
, связана с затратами на создание генерации хеш-кода для данного Type
. Каждый раз, когда вы вызываете TryGetValue
, необходимо вызвать Type.GetHashCode()
. GetHashCode является виртуальным (не может быть встроенным), и этот метод вызывает 3 других виртуальных метода. В конце статический (внешний) вызов выполняется в RuntimeHelpers.GetHashCode(key)
.
Type
в качестве ключа и вместо вызова Type.GetHashCode()
вы должны называть RuntimeHelpers.GetHashCode(key)
.
ОБНОВЛЕНИЕ (2013-04-05):
Несколько месяцев назад я попытался улучшить производительность контейнера DI, который я поддерживаю, и я играл с оптимизацией словарной части. Я написал свой собственный словарь, который напрямую вызвал RuntimeHelpers.GetHashCode(key)
(и пропустил виртуальные вызовы), но в итоге производительность растет там, где такая небольшая (около 1% в тестах Palme), что я решил вернуть эти изменения кода. Поэтому мое нынешнее понимание заключается в том, что реальные затраты на производительность с Dictionary<Type, X>
- это все, что происходит внутри RuntimeHelpers.GetHashCode(key)
.