ViewBag vs ViewData performance difference in MVC?
Asked Answered
S

2

35

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?

Scheming answered 22/2, 2011 at 13:52 Comment(0)
A
48

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.

Archaeornis answered 22/2, 2011 at 13:56 Comment(4)
Could you like...put a conclusion so lazy people like me who just wants to know which is better can just read the last paragraph lol?Spinning
@Shawn Mclean - lol yeah you're right! Updating my answer :)Archaeornis
Something to note that made me look for an answer to this question myself, VS2013 shows a A first chance exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll error when trying to access it in debug. Whether this only happens in debug or normally as part of the process, it is something to consider. ViewData does not throw that. This is when the value does exist.Ellon
Yup this is standard procedure for all dynamic code where the dynamic implementation does not find a member with the given name (outside of types which might implement the dynamic interchange themselves through IDynamicMetaObjectProvider) And it's fair to say that this contributes certainly part of the speed differenceArchaeornis
P
9

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.

Photoelectric answered 22/2, 2011 at 13:56 Comment(4)
I agree, it's more of an academic curiosity.Scheming
The only solution here is to write a little test with for(i=0; i<1000000; ++i)Photoelectric
@CallMeLaNN - test to difficult for you to do yourself?Photoelectric
I its easy but I am not looking for this right now as a serious performance unless someone claim it. Just for info to take into account in future development. If I do the test right now and performance is critical for me, I also want to know result from others since it may varies based on the test algorithm.Impending

© 2022 - 2024 — McMap. All rights reserved.