什么表现更差:反思还是拳击?
我正在致力于创建自己的 DI 框架,该框架创建委托工厂作为学习练习。我构建类型化委托的方法是使用表达式创建一个函数,该函数引用我的容器和任何构造函数参数来调用静态方法。
这提出了一个关于值类型的有趣问题。哪个是性能最好的:
a) 使用反射选择具有正确数量参数的静态泛型方法,然后使用 MakeGenericMethod 删除泛型
b) 使用老式的 params Object[] 并接受拳击?
I'm working on creating my own DI framework that creates delegate factories as a learning exercise. My way of building typed delegates is to use expressions to create a function that calls a static method with reference to my container and any constructor params.
This thrown up an interesting question with regards to value types. Which is the most performant:
a) Using reflection to select a static generic method with the correct number of parameters then use MakeGenericMethod to remove the generics
b) Go for the old fashion params Object[] and take the hit on boxing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
IME,拳击时间与反射相比根本不算什么。
IME, boxing time is nothing compared to reflection.
我猜反射会慢很多,可能是数量级。
不过,这很容易上手,尝试一下并发布你的结果:)
I'd guess that reflection would be alot slower, probably orders of magintude so.
It's pretty easy to bench though, give it a go and post your results :)
在这种情况下,装箱将比反射快几个数量级。
当然,您始终可以缓存反射结果。
In this case, boxing will be orders of magnitude faster than reflection.
Of course, you could always cache the reflection results.
总的来说,我想说即使拳击速度较慢(在某种程度上不明显),它也是正确的方法。反射是一种促进某种元编程的工具 - 当您必须对代码本身进行一些工作时,而不是促进您的应用程序业务逻辑,因此您不应该在没有充分理由的情况下使用它。程序员应该首先从物理领域思考。也就是说,就您而言,这可能并不重要,因为您已经采用了元方式我认为。使用
object
仍然可以在一定程度上为您提供编译时安全和更好的维护。正如其他人所说,反射在这里是较慢的(除非您不缓存)。另一件对拳击有利的事情是在处理反射时你很可能正在拳击。反射 API 始终处理
对象
,因此如果您要返回某些实例值,则必须拆箱。同样, 调用值类型实例上的 GetType
首先将其装箱为object
,如果您没有类型参数而只有实例,则可能必须这样做。但更好的选择是依赖泛型。 此处详细介绍了一些不错的模式。
In general, I would say even if boxing had been slower (to an extent not noticeable), its the right way to go. Reflection is a tool to facilitate some sorta meta-programming - when you have to do some work over the code itself, and not to facilitate your applications business logic, and hence you shouldn't use it without a good reason. A programmer should think from the physical domain first. That said, in your case it probably doesn't matter since you're already going the meta way I think. Using
object
still gives you compile time safety to certain extent and better maintenance.As others have said, reflection is the slower one here (unless you dont cache). Another thing that comes to boxing's favour is that you are most probably anyway boxing when dealing with reflection. The reflection API always deals with
object
, so if you are getting back some instance value you have to unbox. Similarly, callingGetType
on a value type instance first boxes it toobject
which you may have to if you don't have the type argument, but only the instance.But a better alternative is to rely on generics. Some nice patterns are detailed here.
如果必须处理一百万个项目,则对每个项目进行装箱将比不装箱处理它们的效率低,但比使用反射处理每个项目的类型要快得多。
另一方面,在许多场景中,可以通过在类型
T
上使用一次反射来处理某种泛型类型T
的一百万个项目,以构造一个对象,该对象可以在不装箱的情况下处理T
类型的内容,然后在程序的生命周期内缓存其结果。这就是EqualityComparer.Default
之类的东西的工作原理。这种方法很容易比装箱每个项目快一个数量级以上。If one has to process a million items, boxing each item will be less efficient than processing them without boxing, but will be much faster than using Reflection to process the type of each item.
On the other hand, in many scenarios it will be possible to process a million items of some generic type
T
by using Reflection once, on typeT
, to construct an object which can process something of typeT
without boxing, and then cache the result of that for the life of the program. This is how things things likeEqualityComparer<T>.Default
work. Such an approach can easily be more than an order of magnitude faster than boxing each item.