Некоторые люди утверждали, что функция C# 4.0 представила с dynamic
ключевое слово совпадает с, "все - Объектная" функция VB. Однако любой запрос к динамической переменной будет переведен в делегата однажды и с тех пор, делегата позвонят. В VB, при использовании Object
, никакое кэширование не применяется, и каждый запрос к невведенному методу включает большое отражение под капотом, иногда всего огромную 400-кратную потерю производительности.
Имеет динамическая оптимизация делегата типа и кэширующийся также добавленный к VB невведенные вызовы метода, или VB's не вводится Объект, все еще настолько медленный?
Некоторое исследование и лучшее чтение , ранее упомянутого в статье , упомянутой Хансом Пассантом, приводит к следующему выводу:
IDynamicMetaObjectProvider
, если хотите явно поддерживать динамику, компилятор VB.NET обновлен, чтобы распознавать это; Object
будет использовать DLR и кэширование методов, только если объект реализует IDynamicMetaObjectProvider
; IDynamicMetaObjectProvider
, использование Object
для таких типов или ваших собственных типов вызовет классические, не- кешированный VB.NET с поздним связыванием. Некоторые люди (среди которых Ханс Пассант, см. Его ответ) могут задаться вопросом, почему кеширование или отсутствие кеширования при позднем связывании может иметь значение. На самом деле, это имеет большое значение как в VB, так и в других технологиях позднего связывания (помните IQueryInterface
с COM?).
Позднее связывание сводится к простому принципу: учитывая имя и его объявления параметров, перебрать в цикле все методы этого класса и его родительских классов с помощью методов, доступных через интерфейс Type
( а в VB метод, свойство и поле могут выглядеть одинаково, что делает этот процесс еще медленнее). Если вы считаете, что таблицы методов неупорядочены, то это намного дороже, чем один прямой (т. Е. Типизированный) вызов метода.
Если бы вы могли найти метод один раз, а затем сохранить указатель метода в таблице поиска, это значительно ускорило бы этот процесс. Привязка кэшированного метода в DLR идет на один шаг дальше и заменяет вызов метода указателем на фактический метод, если это возможно. После первого вызова это становится на порядок быстрее для каждого последующего вызова (подумайте, в 200-800 раз быстрее).
В качестве примера того, когда это имеет значение, вот код, который иллюстрирует эту проблему. В случае, когда каждый класс имеет строковое свойство .Name
, но классы не имеют общего предка или интерфейса, вы можете наивно отсортировать списки любого из этих типов следующим образом:
' in the body of some method '
List<Customers> listCustomers = GetListCustomers()
List<Companies> listCompanies = GetListCompanies()
listCustomers.Sort(MySort.SortByName)
listCompanies.Sort(MySort.SortByName)
' sorting function '
Public Shared Function SortByName(Object obj1, Object obj2) As Integer
' for clarity, check for equality and for nothingness removed '
return String.Compare(obj1.Name, obj2.Name)
End Function
Этот код ( по крайней мере, похожий) фактически был запущен в производство с одним из моих клиентов и использовался в часто называемом обратном вызове AJAX. Без ручного кэширования свойств .Name
, уже в списках среднего размера, содержащих менее полумиллиона объектов, код с поздним связыванием стал настолько заметным бременем, что в конечном итоге привел к остановке всего сайта. Отследить эту проблему оказалось непросто, но это уже история для другого раза. После исправления этой проблемы сайт восстановил 95% ресурсов процессора.
Итак, ответ на вопрос Ханса «разве у вас нет больших проблем, о которых стоит беспокоиться?» прост: это большая проблема (или может быть), особенно. программистам VB, которые слишком небрежно подошли к использованию позднего связывания.
В этом конкретном случае и во многих подобных случаях VB.NET 2010, по-видимому, не был обновлен для введения позднего связывания, и поэтому Object
остается злом для тех, кто не знает, и его не следует сравнивать с динамическим
.
PS: проблемы с производительностью позднего связывания очень сложно отследить, если у вас нет хорошего профилировщика производительности и вы не знаете, как позднее связывание реализовано внутри компилятора.
Хороший вопрос. Я предполагаю, что ответ - «Нет», потому что в этой статье в журнале MSDN говорится, что VB.Net был изменен для поддержки среды выполнения динамического языка, и кратко описаны изменения в среде выполнения, но не упоминается кеширование. .
Кто-нибудь знает лучше?
Цитата из статьи о новых возможностях :
Visual Basic 2010 обновлен для полной поддержки DLR в его latebinder
Ничего более явного, чем это. Это DLR, который реализует кеширование.