Действительно ли отражение действительно медленное?

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

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

Спасибо, Bhaskar

Ответ 1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

Обычно я предпочитаю этот подход:

  • написать простой код
  • Измерение производительности
  • оптимизировать самый большой нападающий, при необходимости

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

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

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

Ответ 7

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

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