Wednesday, 28 November 2012

WSE2: Trace Memory 'Leak'

Recently I had to deal with a production server that was chewing through memory at an astounding rate; The web service applications (asp and .net) would start up and idle around the 100MB mark which was acceptable, but after an indeterminate period of time the memory would suddenly grow out to 1.25gig (Server 2003 32bit) and users would start getting out of memory errors, timeouts, or generally degraded performance.

This wasn't exacly a new thing - the server had always used a lot of memory. But why was it suddenly a huge problem?

I thought it was a memory leak in one of my applications - we had just deployed a new feature that handled binary files in memory, perhaps that was leaking? Perhaps someone had dug out an old badly-written form that hadn't been used for years.

I was completely at a loss, and the usual fault finding methods were not cutting it, so I decided to delve into the mystical world of debugging via dump files.

These tools and tutorials set me up, and within a few hours I was away.
http://blogs.msdn.com/b/tess/archive/2008/02/04/net-debugging-demos-information-and-setup-instructions.aspx
http://blogs.msdn.com/b/tess/archive/2008/02/11/net-debugging-demos-lab-2-crash-review.aspx
http://blogs.msdn.com/b/tess/archive/2008/02/20/net-debugging-demos-lab-3-memory-review.aspx
http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx
http://msdn.microsoft.com/en-us/library/bb190764.aspx


After a solid 8 hours of investigation I discovered that there were 30,000+ instances of XML SOAP requests in memory (plus all their strings and encapsulating objects - 1.2 million tiny xml fragments). This is for a job management system and the XML data was all job requests/responses. No reason why these couldn't be in memory, but looking through them some of these requests were going back to the beginning of the year and our staff don't need to refer back to jobs that often.

Armed with this information and some handly debug data pointing the calling assembly of the XML fragments, I discovered two large .webinfo files in the web services directory. These are generated when WSE2 has trace enabled, and they are well-formed XML files.

My theory here is as follows.
When a request comes in WSE has to log it, so it opens the .webinfo file and creates an XML object in memory. This is manipulated, validated, and written back down to file system. When this file gets large enough it starts draining the resources available to the other applications on the server.

The solution, naturally, is to turn tracing OFF. And the problem magically went away.

Now it is interesting to note that the documentation for the trace element/feature mentions that
"Once an application is deployed to production, tracing should not be enabled. Doing so, may eventually deplete the available disk space on the computer running the application."
Considering that hard drive space is cheap this might not be a concern, but if you take into consideration that the log file needs to be manipulated in memory the scope of the choice changes dramatically.

Special thanks to Tess Ferrandez for her excellent tutorials - you helped me save the day!

Wednesday, 7 November 2012

Windows Mobile .NET CF: Form Title Inheritance

I recently came across a series of issues when dealing with my field trial testers for a large-scale PDA deployment. A change I made to the way forms were opened happened to change the title text from the Job Number and was only displaying the name of the application. The original title was only being displayed for testing purposes but it turns out it was a handy feature for them to have.
In the process of our testing they had also picked up how to use Task Manager (Running Programs) on the PDA so were experiencing unexpected results when they lost the app behind their email client, and selected the wrong form out of the many that were showing in in the Running Programs.

This prompted me to try to get a fix - both to their newfound usability issue and to the problems they were causing when messing around in task manager. Savvy users!

Case:

  • You are developing a WM6.1 .NET CF 2.0/3.5 (or similar) forms app that has multiple forms.
  • You do want to be able to change the visible title (Form.Text) at the the top of the screen
  • You do not want multiple forms to display in task manager (Memory > Running Programs)

Example Situation:

Your user starts the app and is presented with a login form. After logging in they are presented with a menu form (a bunch of buttons), and from here they open a Job List Form, and then select and open a job in the Job Details form.
You require the title of the application to read 'Job Manager' until they open a job, then you require it to display the job number (J123456). Only one job at a time can be open and jobs must be closed before they go back to the previous page.
You also require that if the users go into the task manager they only see the currently active form.

Rules of engagement:

If Form.Owner is set the child form will inheret the parent forms title
If Form.Owner is set the child form cannot change the title
If Form.Owner is not set the child form is able to change the title but the parent form will display in task manager.
If a foms title is set to an empty string it does not appear in task manager.

Solution:

When opening a child form, set the parent forms title (.text property) to an empty string to hide it from task manager, don't set the child forms owner, and display the form. After returning from the child form reset the title for the parent form.

If dealing with multiple levels of forms, as with the Example Situation:
Each form needs to specify what the title will be - this means that each form title will need to be set to 'Job Management' when active and '' when opening a child form. When we get to the Job List Form and select a job the Job List form will set it's title to '' and the child form (Job Details) will set its title to whatever the Job Number is. In the case of this Job Details form it has multiple child forms capturing various aspects of the job data - but all of these are opened using Form.Owner to retain the title of the parent form. If we so desired we could treat this form the same as all the others in the solution so far, and have our titles read 'J123456 - Widgets' or 'J123456 - Sign Off', but due to the screen res on most WM6.1 devices this wouldn't fit anyway.

Point of interest - if you don't set the name of a child form (and there is no name to inherit etc) the title will say 'Start' - this is the Start Button (I actually got confused for a second there).

In hindsight this does seem like a bit of a hack, but the more I develop in Windows Mobile 6.1 and .NET CF the more I realise that this is the way things are done.

Sample code:

string myTitle = this.Text;
this.Text = "";
this.SuspendLayout();
frmIndex.ShowDialog();
this.ResumeLayout();
this.Text = myTitle;
The Suspend/ResumeLayout() calls are not specifically required for this example however I have had problems with the parent form responding to events and consider it important to remember when opening child forms. Specifically the issues I have had are with textboxes on the child forms automatically calling the SIP and having the call handled by the parent form instead. In my case this resulted in the child form becoming invisible and the parent form showing but being non-responsive. Your results may vary.

References:

http://www.mobilepractices.com/2007/12/working-with-forms-in-windows-mobile.html

Monday, 22 October 2012

Excel: List of sheets in workbook

To get a list of all the sheets in your workbook; right-click on the arrows to the left of the sheet tabs:


The 'More Sheets' option brings up a dialog box containing the full list.