Thursday, 3 June 2010

Memory leak, Dispose() and Using statement (2)

Step 1: Diagnose your code. Find the evil piece.
Probably you know some tools which helps to measure performance and memory usage. Two types of tools can help you in this step. Memory measurement tool and memory explorer tool.
WMI (Windows Management Instruction) does a good job measuring private working set for a defined process or processes. It keeps tracking the memory usage with a configured time interval and saving to spreadsheet or other format files. There is also a user interface so you can see some graph of memory usage.
There are also several memory explorer tools in the market. The one I am using is ANTS memory profiler. It gives a good hint which objects are now inside the memory (heap), and also objects numbers, values and how far they are from the GC root. Even it can compare the memory snapshots at two different time. From my experience sometimes it helps, sometimes not. Memory usage is a complex issue especially when you have a complex system. You got tons of things in the memory. Usually unused objects stay in the memory for a while should be ok as long as they could be collected in the next garbage collection. But the thing is that GC , not you, decides when and how to collect the garbage. So it is really hard to tell if these unused objects in the memory are new or survive in the last garbage collection. You have to run the tool for a longer time to compare the several snapshots.

Go back to the memory leak problem I fixed. Some context. The project size is big and I am not familiar with every module. And no way to be familiar with every module of this big project.
I am a bit lucky this time because I paid attention to the memory usage of the system for a long time. Sometime I left the system running over night and there was no obvious memory leaking. So think about the developing environment and production environment and get some idea.
  • Database size. I believe production environment has a much bigger database size.
  • LDAP. Production environment uses LDAP for authentication. I do not.
  • I did not do a real long test.
It did not take me very long time to narrow down to one suspicious module. I spent almost one day on some suspicious UI things because ANTS memory profiler told me that there are a lot of objects staying in the memory relevant to UI refreshing. But after some painful code checking and more tests I found out that number of that part of objects went down after it reached a limit. And it does it consistently. So forgot about it and moved on. I also did spend some time to increase my database size and did more tests. It turned out database size has nothing to do with memory leaking at this time.

I focused on several public methods after verifying that this module is the evil one with several tests. It became easy now. Tested one method each time after mocking up the other suspicious methods. I were almost there after several tests. I can tell which lines are leaking memory. But I can not tell if they are all of the evil pieces.

To be honest ANTS memory profiler does not help a lot in this step and drove me to the wrong direction sometimes.


Memory leak, Dispose() and Using statement (1)

The project I worked on has a huge memory leak in production environment. It was reported recently by onsite engineer. I believe this problem exists for a long time. It hid very well previously.

Memory leak is always not easy to fix. First step you have to find out which place has memory leak. It is painful to go through this process. Next step you have to release the memory properly. It sounds simple, but not because CLR is supposed to take care of the memory stuff. It works as a memory manager for .Net application, right? Something must be wrong if CLR can not do its job well which means somewhere in your code breaks the default garbage collection rules. Of course third step you have to run pair testing for over 12 hours to see the results. It is not compulsory to be 12 hours. 2 hours even 1 hour is still good for the middle test. It has to be long enough to make you confident that your modification works or it does not work. But the final test has to be more than 12 hours because this time you want to show your managers and team members that your modification works. Generally you will see some nice results after several times tests. Another annoy thing about memory leak problem is that memory leak usually does not happen at only one place. You have to find them piece by piece and fix them piece by piece. The test result will be a bit nicer, a bit nicer, a bit more nicer... Usually not big change at one time. It also means memory leak problem is time consuming.

So to fix memory leak problem, probably you will go through hopeless, depressed, disappointed, and annoyed. And most of the important hopefully you will feel happiness in the end . I reach the last one every time luckily.

Many thanks to my lovely and funny colleagues, Colin, Takashi, and Thura. They make my job more interesting.

Tuesday, 13 April 2010

A Win32Exception is thrown - The file size exceeds the limit allowed and cannot be saved

Currently we got an exception A Win32Exception is thrown - The file size exceeds the limit allowed and cannot be saved. It seems it is a bug from Windows after searching online for a while.
My colleague confirmed this with his change set although I do not know it works or not. And he referred to an article about this exception. The link is here http://daniel-richardson.blogspot.com/2008/12/handling-eventlogentrywritten-event-for.html

"A Win32Exception is thrown if EnableRaisingEvents is set to true on an empty EventLog. The exception message is "The file size exceeds the limit allowed and cannot be saved".
The workaround for this is to check if the EventLog is empty and write an entry if necessary before setting EnableRaisingEvents to true."
Or you do not set EnableRaisingEvents to true for no good reason.

Thursday, 1 April 2010

ActiveMQ Message Routing

There are several things to think about when you design the ActiveMQ message routing.

1) JMS Selectors. Selectors are a way of attaching a filter to a subscription to perform content based routing. Selectors are defined using SQL 92 syntax and typically apply to message headers; whether the standard properties available on a JMS message or custom headers you can add via the JMS code.
ActiveMQ message properties and JMS message properties should be considered when using JMS selectors.

2) Wildcards. ActiveMQ supports destination wildcards to provide easy support for federated name hierarchies. A subscriber could use wildcards to define hierarchial pattern matches to the destinations to subscribe from. Note wildcards are not part of the JMS specification so are custom enhancements.
I think this feature is quite useful when some messages are only interesting to part of the consumers and relation structure is complex.

3) Advisory Message. It is kind of administrative information of ActiveMQ which helps to watch the system by subscribing to regular JMS messages. By default this is disabled.

4) Message Redelivery. Messages are redelivered to a client when any of the following occurs:

  1. A transacted session is used and rollback() is called.
  2. A transacted session is closed before commit is called.
  3. A session is using CLIENT_ACKNOWLEDGE and Session.recover() is called.
(DLQ means dead letter queue)

Friday, 26 March 2010

Host multiple services with multiple configuration files

Definitely it should be good if we could do this - Host multiple services with multiple configuration files. I found a nice post talking about the way the author implements this. Basic idea is to use different AppDomain for different services and handling loading, hosting service manually. Here is the link: http://blogs.microsoft.co.il/blogs/alon/archive/2008/03/12/hosting-plug-in-wcf-services.aspx

I am not sure if this is a good idea. Creating different AppDomains in one process is a little scaring. Do not know how to catch thread level exceptions for each domain. It might be possible to do it. Have not tried. And another thing is how to handle threading context. Not sure. To be honest, I did not we could have different App.Domain in one process. Let's find out more about App.Domain.

===later added
By reading a little bit about App.Domain. I think it might be a good idea. Process is a concept of Windows OS. App.Domain is a concept of .Net Framework. It is about CLR running time resource. It might be good to separate AppDomain for different services.

Friday, 19 March 2010

Properties.Settings.Default.Save() saves to which file?

This did bother me for a while.

There are two options for Scope when we try to add a setting. User and Application. Both default settings are stored in the app.config of this project.

Where will it be saved if user changes the setting in the running time?
The save will save to app.config of the project if it is a application level setting. But it will save to C:\Documents and Settings\[user]\Local Settings\Application Data\[application_name] folder if it is a User level setting.

You can only get the default setting back by deleting the XML files in the above folders and run your application.

Wednesday, 3 March 2010

SharePoint 2010 Preliminary System Requirements

I probably will work on SharePoint for a while.
Microsoft announced preliminary system requirements for SharePoint server 2010. Obviously it goes for some big enterprise with enough budget.
  1. SharePoint Server 2010 will be 64-bit only.
  2. SharePoint Server 2010 will require 64-bit Windows Server 2008 or 64-bit Windows Server 2008 R2.
  3. SharePoint Server 2010 will require 64-bit SQL Server 2008 or 64-bit SQL Server 2005.