Holy Viewstate Batman!

This is my favourite kind of post because it spawned from a question somebody asked me earlier in the day.  The question was about storing ASP.Net viewstate on the server side to avoid the time and bandwidth used round tripping it to the client and back.  Though I was asked about implementation details at the time I want to step back and have a more complete discussion around whether this is a good thing to be doing or not.

Make Sure It's The Right Problem

The challenge is really a performance optimisation and we are normally after a few key factors which can be easily measured:

  • Rendered size of the HTML.
  • Time taken for the client to load the page.
  • Bandwidth used by both the client and the server.

Each of these factors has a huge number of potential causes so it is important to make sure that viewstate isn't a misdiagnosis causing you to spend a lot of effort in the wrong place.  I do want to go into other possible causes some time but for now I'm going to assume that viewstate is the problem.  The ideal process for any sort of performance optimisation goes something like this:

  1. Define a performance goal.
  2. Measure performance.
  3. If the goal is met, stop.
  4. Make a change.
  5. Go to 2.

Structured programming aside the most important thing is the measuring.  There is a very simple way to measure your viewstate that anyone can do with the tools they already have.  First browse to the target page in your web browser and view the source code.  Delete everything except the encrypted viewstate tag.  Save the file to disk and have a look at it's properties to see the size.  Here's an example from Intergen's homepage:

 Viewstate Properties

235 bytes, pretty good so I wont be spending any time on that.  This isn't a precise measure if you do it consistently it is quite effective for measuring the effect of changes.  You may want to measure the overall page size rather than just the viewstate as you typically change them together when optimising.  This is a pretty primitive way to measure things so I strongly recommend you go and grab something like Firebug for Firefox which is my number one web debugging tool.

Sweep It Under The Rug

The problem I have with the original proposal to store the view state on the server side is that is hiding the symptoms more than it is addressing the cause of the problem.  Viewstate simply shouldn't be big enough to cause a problem and if it is you need to look carefully at the way your pages are constructed.

Storing viewstate on the server has a number of subtle side effects you should carefully consider.  If you haven't done so already I suggest you have a read of my earlier post on different places to store data in ASP.Net.  In general you will find that you end up using server resources and processing time to reduce the rendered page size.  This might be a reasonable tradeoff but it also changes the characteristics of viewstate.

Viewstate is per rendered page instance so if you store it on the server you will need a way to match it to each instance that is sent to the client.  The first instinct is usually to push the data into session but it is becoming quite common for users to browse with multiple windows open so you will need to cache viewstate for multiple page instances at any one time.  The same problem is caused by the insidious back button.  Since you are doing this because your viewstate is too large the persistence of the data on the server is likely to cause it's own performance problems.

You can push the data out to a SQL database for more robust storage but you will then have the problem of deciding when to expire the data and remove it from the database.  This also adds two additional database queries to each page request which can be quite significant when you take network latency into account.

In general my advice is to leave the viewstate where it is and concentrate on making sure you don't have too much of it instead.

How Much Is Too Much?

Just how much viewstate you should allow in your pages depends a lot on who your target audience is.  In a tightly controlled intranet environment where all users are on high bandwidth connections no one is going to notice 50k of viewstate.  On the other hand mobile devices are becoming more common so watch out for the guy trying to view the company intranet on his cell phone from a back country paddock.  On the public Internet conditions are much less predictable and I would suggest setting a much lower limit for yourself such as 5k.  These are very generous limits and a lot of people would push you for a lot less but that's a call you need to make for your projects requirements.

Where possible always develop with viewstate in mind and make checking page sizes part of your normal testing cycles.  I highly recommend setting up a test environment that closely resembles your target audience including low bandwidth connections where appropriate.  This can be achieved using a number of tools such as applications you can install on your computer and certain firewalls.  With a little effort to keep things light you should be able to keep viewstate down to one or two kilobytes per page.

If you are really determined you can work  quite happily with no viewstate at all though ASP.Net makes this difficult out of the box.  Viewstate is a huge convenience feature that can save you a lot of time if used carefully.

Strategies For Reducing Viewstate

The best advice I can give for reducing viewstate is to find all of the data grids in your site and delete them.  Repeating controls such as a data grids, data lists, repeaters, grid views and drop down list are the number one culprit for generating viewstate.  Sometimes the problem isn't with the control itself but with controls nested inside it that are being repeated a number of times.

A lot of controls generate viewstate unexpectedly.  A great example if the label control which Microsoft suggests you use in all of its tutorials.  As well as saving all of its properties a label control generates viewstate for the text you place in it so you are usually better off using a literal control and formatting the text with CSS.  One label by itself isn't likely to cause a problem but when it is inside a repeating control it can be significant.

Every ASP.Net control has an EnableViewState property which you can set to false to make sure that that control doesn't generate any viewstate at all.  It's the next best thing to deleting the control entirely.  Personally I feel that this should default to false so that you have to think about it and turn it on only when necessary.

Since you can't just delete every offending control you need to be a little more cunning.  Start by asking yourself why you actually need viewstate and you'll probably find that there are a few key properties of each control that you are interested in.  Consider disabling the default viewstate for the control and storing these properties yourself.  Typical examples include sorting and paging information for lists of data.

Disabling view state often has the effect of making your data disappear on postback.  Think about this carefully because it's a good hint as to why you are getting so much viewstate in the first place.  Recently I have started to favour disabling viewstate and rebinding all data on a postback.  This usually generates more load on the database but ASP.Net has excellent support for server side data caching to mitigate this.

Finally remember that other web frameworks get along just fine without viewstate.  Viewstate and postbacks are simply wrappers on basic HTTP technology that trade flexibility and control for increased developer productivity.  As with all generalisations they come with drawbacks and in this case it's performance that takes a hit.

If you are really serious about the quality of your pages you need to get intimate with the layers underneath ASP.Net.  Some of my earlier posts on lightweight web forms might be a good starting point and they also include some information on reducing page size in general.  If you think you have a good handle on HTML I suggest book marking the HTML specification at W3 because it's packed with all the details and insights you need to achieve HTML Zen.

I am considering writing a little more about page size in general but if there are any particular topics you'd like me to cover in more depth just let me know.

Labels:

11/08/2008 04:29 AM (UTC -07:00)