MVC 中 ViewBag 与 ViewData 性能差异?

发布于 2024-10-18 17:12:55 字数 106 浏览 9 评论 0原文

我知道 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 技术交流群。

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

发布评论

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

评论(2

薄凉少年不暖心 2024-10-25 17:12:55

好吧——我最初的回答基本上是“不”——是时候掉头了。

在完美的动态世界中,它应该是“不” - 但经过仔细检查,会发现要么没有区别(考虑到JIT魔法),要么可能稍微慢一点,尽管还不足以保证不使用它(我当然是)。

理论上,如果实现得当,ViewBag 最终将优于 ViewData 字典的使用,因为表达式的绑定(例如 ViewBag.Foo)在不同的环境中得到了很好的缓存。编译器将生成的 CallSite(反映一个读取或写入 ViewBag 的方法,您就会明白我的意思)。

DLR 的缓存层有详细记录(如果有点难以理解)一旦你深入了解就会明白),但基本上运行时会尽力“记住”给定值实例在绑定它后的位置 - 例如通过 Set 或 Get 语句。

但是缓存及其使用和有效性完全取决于类/接口的底层实现,例如DynamicObject, IDynamicMetaObjectProvider 等;以及 Get/Set 表达式绑定的最终结果。

对于 MVC 内部 DynamicViewDataDictionary 类 - 它最终会绑定到此:

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
  result = this.ViewData[binder.Name];
  return true;
}

For var a = ViewBag.Foo

public override bool TrySetMember(SetMemberBinder binder, object value)
{
  this.ViewData[binder.Name] = value;
  return true;
}

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 the ViewBag 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:

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
  result = this.ViewData[binder.Name];
  return true;
}

For var a = ViewBag.Foo

And

public override bool TrySetMember(SetMemberBinder binder, object value)
{
  this.ViewData[binder.Name] = value;
  return true;
}

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 of ViewBag, instead of the other way around, and had ViewBag then been implemented with even something like ExpandoObject, then it might be a different story - as the dynamic implementation of ExpandoObject 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.

迷雾森÷林ヴ 2024-10-25 17:12:55

我没有做过任何测试,但我的直觉是,在现实世界中,差异可以忽略不计。您可能会在每个页面上访问它几次,并且几个 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.

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