Получила ли Object в VB 2010 такую ​​же оптимизацию, как и динамическая в C # 4.0? - PullRequest
6 голосов
/ 13 апреля 2010

Некоторые люди утверждают, что функция C # 4.0, введенная с ключевым словом dynamic, такая же, как функция "все является объектом" в VB. Однако любой вызов динамической переменной будет преобразован в делегат один раз, и с этого момента будет вызван делегат. В VB при использовании Object кэширование не применяется, и каждый вызов нетипизированного метода включает в себя множество скрытых отражений, что иногда приводит к колоссальному 400-кратному снижению производительности.

Был ли добавлен динамический делегат-оптимизация и кэширование также к вызовам нетипизированных методов VB, или нетипизированный объект VB все еще такой медленный?

Ответы [ 3 ]

5 голосов
/ 01 июня 2010

Решение

Некоторое исследование и лучшее прочтение , ранее упомянутое Хансом Пассантом в статье , приводит к следующему выводу:

  • VB.NET 2010 поддерживает DLR;
  • Вы можете реализовать IDynamicMetaObjectProvider, если вы хотите явно поддерживать динамику, компилятор VB.NET обновляется, чтобы распознавать это;
  • VB Object будет использовать только кэширование DLR и методов, если объект реализует IDynamicMetaObjectProvider;
  • Типы BCL и Framework не реализуют IDynamicMetaObjectProvider, использование Object для таких типов или ваших собственных типов вызовет классическое не кэшированное позднее связывание VB.NET.

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

Некоторые люди (среди которых Ганс Пассант, см. Его ответ) могут задаться вопросом, почему кэширование или неэширование в позднем связывании может иметь значение На самом деле, это имеет большое значение, как в 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 остается злом для незнающих и не должно сравниваться с dynamic.

PS: проблемы с поздним связыванием очень трудно отследить, если только у вас нет хорошего профилировщика производительности и вы не знаете, как компилятор реализует позднее связывание внутри.

2 голосов
/ 13 апреля 2010

Цитата из Что нового в статье :

Visual Basic 2010 был обновлен до полностью поддерживать DLR в его latebinder

Не может быть более явным, чем это. Это DLR, который реализует кэширование.

0 голосов
/ 13 апреля 2010

Хороший вопрос. Я предполагаю, что ответ «Нет», потому что эта статья в журнале MSDN говорит, что VB.Net был изменен для поддержки динамического языка Runtime, и кратко описывает изменения времени выполнения, но не упоминает кэширование ,

Кто-нибудь знает лучше?

...