As I try to optimize the bandwidth on the site using caching, compression etc it still remains very high. There are substantial improvements on that front in the upcoming SP2 but that does not mean those of us stuck in the present are completely helpless. If you use a tool such as fiddler to analyze the traffic on a postback (for example, when you change the account type – which does not actually result in any visible change on the UI) you may see something like (note, this is uncompressed):
Request Count: 1
Bytes Sent: 17,790
Bytes Received: 184,648
That’s a pretty big chunk – both on the way in and out.
For comparison here is gmail when I browse from message to message (uncompressed):
Request Count: 1
Bytes Sent: 1,295
Bytes Received: 7,521
Well part of it is just the nature of the ASP.NET UpdatePanel – they practically resend the whole page every time so it is bound to take a good bit more space. But another culprit is the ViewState – this is something that ASP.NET uses to “remember” what is displayed on the browser (since fundamentally, the web is stateless – if you say you want to view the 3rd row in the grid, the server has to have some way to remember what this 3rd row is pointing to). What happens is the server takes all (or most) of the values on the page, and their corresponding data sources, serializes them to text, and stick them in a hidden field on the page as something like this:
/wEPDwUENTM4MQ9kFgJmD2QWAgIBD2QWDgICDw8WAh4EVGV4dAUOTmljb2xhcyBHYWxsZXJkZAIGDw8WBB4IQ3NzQ2xhc3MFBk5hdkJhch4/wEPDwUENTM4MQ9kFgJmD2QWAgIBD2QWDgICDw8WAh4EVGc+bDAwJFRhYkNvbnRyb2wkZWxlb … 11000 more characters in between … 9nZE+NljKHHLWlju6N/3/hWmlJpeFXEXyFTQgICZGQCDA9kFgQCAQ9kFgJmD2QWAgIBD2QWAmYPZBYgAgEPDxYEHglNYXhMZW5ndGgCgAEfAAUZQ2VhWmlJpeFX
So you have 11 to 30 kb of “stuff” to pass back and forth on each and every post, not to mention the valuable CPU it takes to serialize and deserialize it. Usually it is rather neat to have it on the browser rather than on the server because it means if your session is torn (for example because the web server restarted) you will keep this viewstate. However this is rather moot on Saleslogix since the user is kicked out in that event anyway… so why not leave it on the server in the first place? Turns out Microsoft thought of that too and they provided us with a way to store the ViewState in the session. Saves the bandwidth and the CPU time to handle it (session values are stored “as-is” in memory so it is pretty fast). There are posts describing the process here and here – I am including both because I took an in-between approach. Once I did that I reduced the ViewState to this (it still needs a key to be able to look up the viewstate in the session):
/wEPZwUPOGNjMDFjZGYxNWZjYmViQpgJqyUrZohSJ3XG/uZnVdKp1Vk=
and the data transmitted on a simple postback to this:
Request Count: 1
Bytes Sent: 7,740
Bytes Received: 158,740
It yields a small but perceptible speed improvement on postbacks (the improvement is rather negligible on page changes though – when you switch from contact to account, for example). One downside is it will require a bit more memory on the server side but even at an extra 600 kb per user (enough for 20 of the biggest viewstates) it is only a few hundred megs.
The steps were as follows:
- Created a page adapter called “SessionViewStatePageAdapter” under the App_Code folder – see http://msdn.microsoft.com/en-us/library/system.web.ui.sessionpagestatepersister.aspx for the code, mine looks like this:
public class SessionViewStatePageAdapter : PageAdapter { public override System.Web.UI.PageStatePersister GetStatePersister() { return new SessionPageStatePersister(this.Page); } }
- Add an “App_Browser” folder to the site (it shows up as an option in Visual Studio) and drop a file “Default.browser” with this content:
<browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="System.Web.UI.Page" adapterType="SessionViewStatePageAdapter"/> </controlAdapters> </browser> </browsers>
- Add this tag to the web.config (under system.web), otherwise only part of the ViewState will be affected:
<browserCaps> <case>RequiresControlStateInSession=true</case> </browserCaps>
- In this state the server will get confused if the user opens more than 9 windows (not including the “in-page” popups) so I increased that to 20 by adding this under system.web in web.config:
<sessionPageState historySize="20"/>
All in all a decent improvement for a minimal effort.