October, 2008

Posts
  • PFE - Developer Notes for the Field

    SN.EXE and Empty Temp Files in %TEMP%

    • 0 Comments

    If you have a build server and are doing delay signing this is probably of interest to you.  When delay signing the final step is to post build run the following command:

    sn -R myAssembly.dll sgKey.snk

    I have seen build setups that basically output all binaries to one folder and then run a loop across all the DLLs executing this command.  That way everything is fixed up and ready for the devs to run.  This way you do not have to worry about adding a post build step to each project or you can add one common script to each project.  The release builds of course get fully signed but for daily/rolling builds this works just fine.  Until you check out your temp directory. 

    It turns out for each call to SN.EXE a TMP file is generated.  These TMP files look like this:

    C:\temp>dir
    Volume in drive C has no label.
    Volume Serial Number is 1450-ABCF

    Directory of C:\temp

    12/11/2007  12:39 PM    <DIR>          .
    12/11/2007  12:39 PM    <DIR>          ..
    12/11/2007  11:17 AM                 0 Tmp917.tmp
    12/11/2007  11:17 AM                 0 Tmp91C.tmp
    12/11/2007  11:17 AM                 0 Tmp921.tmp

    You probably noticed that these are 0 byte files which means space is not an issue but if you have a ton of these it can slow your hard drive down.  Also, the actual SN.EXE process can start slowing down. 

    If you have 100 DLLs and are doing 30 builds a day that is 3,000 temp files.  Now, let’s say you build debug x86, debug x64, release x86 and release x64 that is now up to 12,000.  After a couple of days you could imagine how many files. 

    I was working on this and we found out that SN.EXE is not actually the problem here (Thanks to Scot Brennecke).  The issue is in the Crypto APIs that SN.EXE uses.  These APIs are the ones that create and do not clean up the TMP files.  It turns out that there is a hotfix for this if you are using Windows Server 2003:

    On a Windows Server 2003-based client computer, the system does not delete a temporary file that is created when an application calls the "CryptQueryObject" function
    http://support.microsoft.com/kb/931908

    After applying this hotfix the temp files are no longer created and life was happy.  I just thought I would share because the connection between this hotfix and the problem was not immediately obvious.

    Have a great day!

    Zach

  • PFE - Developer Notes for the Field

    Debugging Large ViewState

    • 1 Comments

    This week I have been working with a customer that had pretty large ViewStates that were getting pushed up and down between the client and the server.  The application was moving about 200+ KB of ViewState between the client and server.  This is something we picked out quickly as a scale issue.

    Now Tess has a great blog on why this is a problem from a memory perspective and provides some background on the issue:

    ASP.NET Memory – Identifying pages with high ViewState
    http://blogs.msdn.com/tess/archive/2008/09/09/asp-net-memory-identifying-pages-with-high-viewstate.aspx

    In this customer’s case we were seeing multisecond times for downloading a page from the server and sending the response back to the server so this was also having an impact on performance even before it because a memory problem.  They would run into the memory issues also once load is ramped up.

    The customer posed the question - “Well how do I know what is in my ViewState and what is causing the bloat?”

    This is a fair question and we referred to Tess’s blog but hit some snags that I wanted to comment on incase other people hit these. (read her blog first for background if you have questions)

    Where is the ViewState? 

    To get started we downloaded ViewState Decoder (2.2) but we could not point it directly at the page due to permissions issues. Therefore we went to pull the ViewState from the “View Source” of the page when viewing in IE.  A problem arose because as we navigated the page we would see the page sizes increase in the IIS logs (SC-BYTES value) but the page remained the same size when we did “View Source”.  Basically if we saved the “View Source” that page was identical even though a number of postbacks had occurred.  When I opened the IIS Log I saw each request and the log reported that SC-BYTES (Bytes Sent) was increasing (almost double the initial page request) so something was not adding up.

    In this application it has one page with multiple tabs and as we move through the tabs the page grows but as we said that was not reflected in the “View Source.”  It turns out after talking with the customer that they are using the Updater Panel from the AJAX toolkit and each of the postbacks is an update to that panel.  These updates are not reflected in the “View Source.” To capture this easily we returned to an old favorite – Fiddler from http://www.fiddlertool.com/fiddler/

    From there we were able to get the ViewState out.  Because this was being sent back to AJAX the ViewState showed up like this:

    |hiddenField|__VIEWSTATE|/wE
    <CLIP>
    EA==|9168|hiddenField|__VIEWSTATEENCRYPTED  

    You will notice that these are not normal tags.  Basically the ViewState continued between the “|”.  We grabbed this but and dropped it into the ViewState Decoder but got an error that the ViewState was invalid:

    There was an error decoding the ViewState string: The serialized data is invalid

    Why is the ViewState string invalid if it worked?

    We puzzled over this for a bit and then I noticed what you may already have noticed in the list of hidden fields:

    __VIEWSTATEENCRYPTED

    It turns out that this indicates that the ViewState is encrypted.  So it was understandable that the tool could not easily decode this via my cut and paste of the ViewState.  We decided to turn off ViewStateEncryption for this troubleshooting since the application was just in test.  Basically we add ViewStateEncryptionMode=”none” for this test to Page Directive on the page.  Then BINGO!  We were able to decode the ViewState and get some rich information.

    Here are some links on encryption:

    @ Page Directive
    http://msdn.microsoft.com/en-us/library/ydy4x04a.aspx

    ViewStateEncryptionMode
    http://msdn.microsoft.com/en-us/library/system.web.ui.viewstateencryptionmode.aspx

    For ViewStateEncryptionMode the default is auto which means if any of your control request encryption using the following API ViewState will get encrypted:

    RegisterViewStateEncryption 
    http://msdn.microsoft.com/en-us/library/system.web.ui.page.registerrequiresviewstateencryption.aspx

    All That Data, There Must be an Easier Way!

    Now as we scrolled through all of the data in the output we could see what is stored in the ViewState but tying back to a particular control is not simple.  Also, since there was so much stored in this ViewState it was impossible to easily know what controls were the worst offenders.  So we moved to one last place – Builtin ASP.NET tracing.  We enabled the tracing because there is a VERY helpful column that gets produced - ViewState Size bytes.  This is done for each control that is rendered and makes short order of what controls are the worst offenders.  You will get output like this:

    Control ID

    Type

    Render Size bytes

    ViewState Size bytes

    ControlState Size bytes

    Control1

    System.Web.UI.WebControls.DropDownList

    0

    1084

    0

    Control2

    System.Web.UI.WebControls.DropDownList

    0

    1084

    0

    Control3

    System.Web.UI.WebControls.DropDownList

    0

    1084

    0

    So there we had it!  Control names and their ViewState Size.  We were able to quickly look at who the worst offenders are and start removing the unneeded stuff and fixing the application.

    Reading ASP.NET Trace Information
    http://msdn.microsoft.com/en-us/library/kthye016(VS.80).aspx

    I hope this adds some additional information this discussion of troubleshooting ViewState.

    Have a great day!

    Zach

Page 1 of 1 (2 items)