在.NET中使用动态类型的性能成本

ser*_*0ne 19 .net c# compiler-construction performance dynamic

在.NET 中使用dynamicvs 的性能成本是object多少?比方说,我有一个接受任何类型参数的方法.例如

public void Foo(object obj)
{
}
Run Code Online (Sandbox Code Playgroud)

要么

public void Foo(dynamic obj)
{
}
Run Code Online (Sandbox Code Playgroud)

ILSpy告诉我,在使用动态代码时,编译器必须插入代码块来处理动态.因此,我想知道是否建议使用动态代替对象,以及这种用法以性能为代价达到什么级别?

Mar*_*ell 47

这在很大程度上取决于确切的情况 - 但是内置了一层缓存,所以它并不像你想象的那么糟糕(它不会每次都进行反射).它也可以根据操作而变化(例如,"提升"可空 - T操作明显变慢).你需要测量,但是在这里我有一些时间用于成员(属性)访问,这是我在做FastMember时所做的:

Static C#: 14ms
Dynamic C#: 268ms
PropertyInfo: 8879ms (aka reflection)
PropertyDescriptor: 12847ms (aka data-binding)
TypeAccessor.Create: 73ms (aka FastMember)
ObjectAccessor.Create: 92ms (aka FastMember)
Run Code Online (Sandbox Code Playgroud)

CAVEAT:这些用于单个测试,可能无法代表您的方案.此代码显示在此处

所以:基于一个简单的测试,比静态常规C#慢约20倍,但比反射快约30倍.

更新:有趣的是,看起来反射在.NET 4.5中变得更快:

Static C#: 13ms
Dynamic C#: 249ms
PropertyInfo: 2991ms
PropertyDescriptor: 6761ms
TypeAccessor.Create: 77ms
ObjectAccessor.Create: 94ms
Run Code Online (Sandbox Code Playgroud)

这里它只比反射快约12倍,因为反射速度更快(不是因为动态变慢).


Jon*_*eet 22

因此,我想知道是否建议使用动态代替对象,以及这种用法以性能为代价达到什么级别?

如果您不需要动态类型,请不要使用它.

如果您需要动态类型 - 例如,如果它避免了一些复杂的反射代码 - 那么使用它并测量性能成本.

成本将严重依赖于您正在做的事情.它几乎总是比静态类型代码更慢,其中等效代码甚至可能,但有很多因素会影响确切的成本.与性能问题一样,编写最干净(不一定是最短)的代码,开始使用,测量性能,如果不符合您的性能目标,请仔细优化(通过频繁的测量来检查您是否正在进行正确的方向).