Отражение действительно медленно? - PullRequest
10 голосов
/ 13 января 2012

Это распространенное убеждение, что рефлексия медленная, и старайтесь избегать ее как можно больше. Но верно ли это убеждение в нынешней ситуации? В текущих версиях .net было много изменений, таких как использование IL Weaving (т.е. IL Emit) и т. Д., В отличие от традиционных способов PropertyInfo и MethodInfo для выполнения отражения.

Является ли это убедительным доказательством того, что новое отражение уже не такое медленное, и его можно использовать. Есть ли лучший способ прочитать данные атрибутов?

Спасибо, Bhaskar

Ответы [ 7 ]

12 голосов
/ 13 января 2012

Когда вы думаете об этом, рефлексия впечатляет своей быстротой.

Кэшируемый делегат из ConstructorInfo или MethodInfo может быть вызван со скоростью, сопоставимой с любым другим делегатом.

Делегат, созданный из ILGenerator.Emit (который, кстати, не новый, он был в .NET начиная с версии 1), также может быть вызван так же быстро.

Объект, полученный посредством излучения или вызоваДелегат ConstructorInfo будет работать так же быстро, как и любой другой объект.

Если вы получаете объект, загружая сборку динамически, используя отражение, чтобы найти вызываемый метод, и вызываете его, и он реализуетопределенный интерфейс, через который вы вызываете его с этого момента, тогда он будет таким же быстрым в использовании, как и другая реализация этого интерфейса.

В общем, отражение дает нам способы делать вещи, которые безесли бы мы могли - если бы вообще могли их делать - должны использовать методы, более медленные как для кода, так и для выполнения.

Это также дает нам средства для выполненияБолее сложные, более хрупкие, менее типичные и менее производительные вещи, чем другие.Практически каждая строка кода C # может быть заменена большим фрагментом кода, который использует отражение.Этот код почти наверняка будет хуже, чем исходная строка в целом ряде способов, и производительность является наименьшим из них.

Вполне возможно, что «избегать отражения, потому что его медленный» совет вытекает из убеждения, что сортировкаразработчика, который сходил бы с ума от любой новой техники только потому, что она казалась крутой, и скорее всего ее предупредят слова «это будет медленнее», чем «она будет менее идиоматичной, более подверженной ошибкам и более сложной»поддерживать".Вполне возможно, что это убеждение является полностью правильным.

По большей части, хотя, когда наиболее естественным и очевидным подходом является использование отражения, оно также не будет менее производительным, чем действительно запутанная попытка избежать его.

Если проблемы с производительностью относятся к чему-либо в отражении, то это действительно относится к скрытому использованию:

Использование dynamic может показаться разумным в случае, когда этого может избежать лишь небольшая работа.Здесь стоит учитывать разницу в производительности.

В ASP.NET использование <%#DataBinder.Eval(Container.DataItem, "SomeProperty")%> проще, но обычно менее производительно, чем <#((SomeType)Container.DataItem).SomeProperty%> или <%#SomeCodeBehindProvidedCallWithTheSameResult%>.Я по-прежнему буду использовать первые 90% времени, а последние только в том случае, если я действительно забочусь о производительности данной страницы или, скорее всего, потому что выполнение многих операций над одним и тем же объектом делает последний на самом деле более естественным.

Таким образом, в целом все остается «медленным» в компьютерах, в то время как они ограничены требованием работать в единой вселенной таким образом, чтобы потреблять энергию и занимать время, для некоторого значения «медленного».Различные методы отражения имеют разные затраты, но и альтернативы тоже.Остерегайтесь не столько рефлексии в тех случаях, когда это очевидный подход, но и скрытый рефлекс, когда другой подход, чуть менее очевидный, может быть полезен.

И, конечно, разумно кодировать с использованием любой техники, которую вы используете.Если вы собираетесь вызывать один и тот же делегат сто раз подряд, вы должны хранить его, а не получать его при каждом вызове, и это будет зависеть от того, был ли путь его получения с помощью отражения или нет.

7 голосов
/ 13 января 2012

Все зависит.
Да, использование отражения, без сомнения, медленнее, чем использование отражения, но вы должны взглянуть на общую картину:

Например, представьте, что ваш код выполняет некоторое отражение, а затем загружает некоторые данные из базы данных по сети.
В этом случае вы можете полностью пренебречь дополнительными затратами на рефлексию, поскольку запрос к базе данных по сети, вероятно, займет гораздо больше времени.

1 голос
/ 13 января 2012

Что вы подразумеваете под упоминанием распространенного убеждения ? Отражение не сплошной блок. Вы должны рассмотреть каждый метод отдельно. Например, создание объекта через конструктор по умолчанию в несколько раз медленнее, чем простой вызов, в то время как создание параметризованного конструктора в десятки раз медленнее. Поэтому, если вы хотите изучить скорость, сделайте тест и сравните конкретные функции, которые вам нужны.

PS. Используя C #, вы всегда можете создавать и компилировать выражения на лету, что, если вам удастся это сделать, будет намного быстрее, чем отражение.

1 голос
/ 13 января 2012

Я бы не стал так сильно беспокоиться о производительности.Не говоря о том, что производительность не имеет значения, но во многих случаях миллисекунда или две не заметны или не стоит выбирать более сложную альтернативу кодирования.Взгляните здесь .

Я обычно предпочитаю такой подход:

  1. написать простой код
  2. измерить производительность
  3. оптимизировать самого большого нападающего, если необходимо
0 голосов
/ 30 декабря 2014

Самоанализ - тяжелая работа.Говоря медленно, это относится ко многим вещам.Вызов метода / конструктора через отражение медленный, но использование отражения только для получения метаданных - нет.

Имейте в виду, что отражение должно использоваться только для извлечения метаданных.Если вам нужно вызывать метод, который запускает что-то, просто генерируйте динамические типы / методы во время инициализации и вызывайте их через интерфейсы / делегаты.

0 голосов
/ 13 января 2012

Если вам нужно взглянуть на атрибуты, применяемые к исходному коду, то вам в значительной степени придется использовать отражение.

Некоторые операции отражения выполняются быстро, например, Object.GetType (), но некоторые операции выполняются относительно медленно, например, Type.FindMethod («MyMethod»).

В целом, я бы сказал, что если ваше приложение иногда использует Reflection, не должно быть проблем с производительностью. С другой стороны, если ваше приложение широко использует Reflection, вы можете заметить некоторую медлительность.

0 голосов
/ 13 января 2012

да отражение медленное, когда мы пытаемся делать громоздкие операции или в цикле. Вы также можете попробовать динамические опции. с динамическим параметром его можно кэшировать, и в конечном итоге он будет быстрее, чем отражение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...