VB 2010 中的对象是否获得了与 C# 4.0 中的动态相同的优化?

发布于 2024-08-28 20:09:00 字数 393 浏览 4 评论 0原文

有些人认为,使用 dynamic 关键字引入的 C# 4.0 功能与 VB 的“一切都是对象”功能相同。但是,对动态变量的任何调用都将被转换为委托一次,从那时起,将调用该委托。在 VB 中,当使用 Object 时,不会应用缓存,并且对非类型化方法的每次调用都涉及大量的底层反射,有时总计会造成高达 400 倍的性能损失。

动态类型委托优化和缓存也被添加到VB无类型方法调用中,或者VB的无类型对象仍然这么慢吗?

Some people have argued that the C# 4.0 feature introduced with the dynamic keyword is the same as the "everything is an Object" feature of VB. However, any call on a dynamic variable will be translated into a delegate once and from then on, the delegate will be called. In VB, when using Object, no caching is applied and each call on a non-typed method involves a whole lot of under-the-hood reflection, sometimes totaling a whopping 400-fold performance penalty.

Have the dynamic type delegate-optimization and caching also been added to the VB untyped method calls, or is VB's untyped Object still so slow?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时常饿 2024-09-04 20:09:00

解决方案

之前提到的文章进行一些研究并更好地阅读Hans Passant 提出以下结论:

  • VB.NET 2010 支持 DLR;
  • 如果您想显式支持动态,您可以实现 IDynamicMetaObjectProvider ,VB.NET 编译器已更新以识别这一点;
  • 如果对象实现了 IDynamicMetaObjectProvider,VB 的 Object 将仅使用 DLR 和方法缓存;
  • BCL 和 Framework 类型不实现 IDynamicMetaObjectProvider,在此类类型或您自己的类型上使用 Object 将调用经典的、非缓存的 VB.NET 后期绑定程序。

背景:详细说明为什么后期绑定缓存可以帮助 VB 代码性能

有些人(其中包括 Hans Passant,请参阅他的答案)可能想知道为什么后期绑定中的缓存或非缓存可能很重要。实际上,无论是在 VB 中还是在其他后期绑定技术中,它都有很大的不同(还记得 COM 的 IQueryInterface 吗?)。

后期绑定归结为一个简单的原则:给定名称及其参数声明,通过 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 属性(已经在包含不到 50 万个对象的中等大小列表中),则后期绑定代码会成为如此明显的负担,最终导致整个站点瘫痪。事实证明很难找到这个问题,但这是另一个故事了。修复此问题后,该站点恢复了 95% 的 CPU 资源。

因此,汉斯的问题“你没有更大的问题需要担心吗”的答案很简单:这是一个大问题(或可能是),尤其是。对于那些对使用后期绑定过于粗心的 VB 程序员。

在这种特殊情况下,以及许多类似的情况,VB.NET 2010 显然没有升级以引入后期绑定,因此,Object 对于不知情的人来说仍然是邪恶的,不应该与 动态

PS:后期绑定性能问题很难追踪,除非您有良好的性能分析器并且知道编译器内部如何实现后期绑定。

Solution

Some research and a better reading of the earlier referred to article mentioned by Hans Passant, brings about the following conclusion:

  • VB.NET 2010 supports the DLR;
  • You can implement IDynamicMetaObjectProvider if you want to explicitly support dynamics, the VB.NET compiler is updated to recognize that;
  • VB's Object will only use the DLR and method caching if the object implements IDynamicMetaObjectProvider;
  • BCL and Framework types do not implement IDynamicMetaObjectProvider, using Object on such types or your own types will invoke the classical, non-cached VB.NET late-binder.

Background: elaborating on why late-binding caching could help VB code performance

Some people (among whom Hans Passant, see his answer) may wonder why caching or non-caching in late-binding could possibly matter. Actually, it makes a large difference, both in VB and in other late-binding technologies (remember IQueryInterface with COM?).

Late-binding comes down to a simple principle: given a name and its parameter-declarations, loop through all the methods of this class and its parent classes by means of methods available though the Type interface (and in VB, a method, a property and a field can look the same, making this process even slower). If you consider that method tables are unordered, then this is easily much more expensive than a single direct (i.e., typed) method call.

If you were capable of looking up the method once, and then storing the method-pointer in a lookup table, this would greatly speed up this process. Cached method binding in the DLR goes one step futher and replaces the method-call with a pointer to the actual method, if possible. After the first call, this becomes an order of magnitude faster for each subsequent call (think 200x to 800x times faster).

As an example of when this matters, here's some code that illustrates this issue. In a case where every class has a .Name string property, but the classes do not share a common ancestor or interface, you can naively sort lists of any of those types like so:

' 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

This code (similar at least) actually made it into production with one of my clients and was used in an often-called AJAX callback. Without manually caching the .Name properties, already on medium sized lists of less than half a million objects, the late-binding code became such a noticeable burden that it eventually brought the whole site down. It proved hard to track down this issue, but that's a story for another time. After fixing this, the site regained 95% of its CPU resouces.

So, the answer to Hans's question "don't you have bigger problems to worry about" is simple: this is a big problem (or can be), esp. to VB programmers who have gotten too careless about using late-binding.

In this particular case, and many like them, VB.NET 2010 has apparently not been upgraded to introduce late-binding, and as such, Object remains evil for the unaware and should not be compared with dynamic.

PS: late-binding performance issues are very hard to track down, unless you have a good performance profiler and know how late-binding is implemented internally by the compiler.

岁吢 2024-09-04 20:09:00

引用新增内容文章

Visual Basic 2010 已更新为
全力支持 DLR 的行动
后期绑定器

没有比这更明确的了。由 DLR 实现缓存。

Quoting from the what's new article:

Visual Basic 2010 has been updated to
fully support the DLR in its
latebinder

Can't get more explicit than that. It is the DLR that implements the caching.

溺渁∝ 2024-09-04 20:09:00

好问题。我猜答案是“否”,因为这篇文章 MSDN 杂志中称 VB.Net 已更改为支持动态语言运行时,并简要描述了运行时的更改,但没有提及缓存。

有谁知道更好吗?

Good question. I'm guessing the answer is "No", because this article in MSDN magazine says VB.Net has been changed to support the Dynamic Language Runtime, and briefly describes changes to the runtime but doesn't mention caching.

Does anyone know better?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文