MVC 中 ViewBag 与 ViewData 性能差异?
我知道 ViewData 和 ViewBag 都使用相同的支持数据,并且在大多数情况下都不如使用强类型模型好。然而,在两者之间进行选择时,ViewBag 的动态特性是否比使用 ViewData 慢?
I know that ViewData and ViewBag both use the same backing data and that neither are as good as using strongly typed models in most cases. However when choosing between the two is the dynamic nature of ViewBag slower than using ViewData?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧——我最初的回答基本上是“不”——是时候掉头了。
在完美的动态世界中,它应该是“不” - 但经过仔细检查,会发现要么没有区别(考虑到JIT魔法),要么可能稍微慢一点,尽管还不足以保证不使用它(我当然是)。
理论上,如果实现得当,ViewBag 最终将优于 ViewData 字典的使用,因为表达式的绑定(例如
ViewBag.Foo
)在不同的环境中得到了很好的缓存。编译器将生成的 CallSite(反映一个读取或写入ViewBag
的方法,您就会明白我的意思)。DLR 的缓存层有详细记录(如果有点难以理解)一旦你深入了解就会明白),但基本上运行时会尽力“记住”给定值实例在绑定它后的位置 - 例如通过 Set 或 Get 语句。
但是缓存及其使用和有效性完全取决于类/接口的底层实现,例如DynamicObject, IDynamicMetaObjectProvider 等;以及 Get/Set 表达式绑定的最终结果。
对于 MVC 内部 DynamicViewDataDictionary 类 - 它最终会绑定到此:
For
var a = ViewBag.Foo
和
For
ViewBag.Foo = Bar;
换句话说- 这些语句被有效地重写为字典索引器的包装器。
因此,没有什么比自己动手更快的了。
ViewData
是从ViewBag
获取数据的,而不是相反,并且ViewBag
甚至可以用ExpandoObject
,那么它可能是不同的故事 - 作为ExpandoObject
的动态实现 更加智能,它采用的缓存规则允许进行一些非常酷的运行时优化。结论
(感谢 Shawn McLean 提出需要一个!)
ViewBag 将比 ViewData 慢;但可能还不足以引起关注。
Okay - my initial answer basically said 'no' - time for a bit of a u-turn.
It should be 'no' in a perfect dynamic world - but upon closer inspection it would appear that there will either be no difference (accounting for JIT magic) or it might be ever-so-slightly slower, although not enough to warrant not using it (I certainly am).
In theory if properly implemented, the ViewBag would ultimately outperform the use of the ViewData dictionary because the binding of the expressions (e.g.
ViewBag.Foo
) is very well cached across the different CallSites that the compiler will generate (reflect a method that does a read or write to theViewBag
and you'll see what I mean).The caching layers of the DLR are well documented (if a little difficult to understand once you get in depth) but basically the runtime does its best to 'remember' where a given value instance is once its bound it - for example via a Set or Get statement.
BUT The caching, its use and effectiveness, is entirely dependent upon the underlying implementations of classes/interfaces such as DynamicObject, IDynamicMetaObjectProvider etc; as well as the end-result of the Get/Set expression binding.
In the case of the MVC internal DynamicViewDataDictionary class - it ultimately ends up binding to this:
For
var a = ViewBag.Foo
And
For
ViewBag.Foo = Bar;
In other words - the statements are effectively being rewritten to wrappers around the dictionary indexer.
Because of that, there's certainly no way it could be faster than doing it yourself.
Were
ViewData
to feed off ofViewBag
, instead of the other way around, and hadViewBag
then been implemented with even something likeExpandoObject
, then it might be a different story - as the dynamic implementation ofExpandoObject
is much more intelligent and the caching rules it employs allow for some pretty cool runtime optimisations.In Conclusion
(thanks to Shawn McLean for suggesting one was needed!)
ViewBag will be slower than ViewData; but probably not enough to warrant concern.
我没有做过任何测试,但我的直觉是,在现实世界中,差异可以忽略不计。您可能会在每个页面上访问它几次,并且几个 CPU 周期不会产生任何影响。人们可以在其他地方找到更大的性能改进。
I haven't done any test but my gut feel is that in real world scenarios the difference is just negligible. You will probably access it a few times on each page and a few CPU cycles won't make any difference. One can find bigger performance improvements in other places.