WYSIWYG

http://kufli.blogspot.com
http://github.com/karthik20522

Thursday, June 11, 2009

Using String.Intern Benefits C#

Recently I was given a daunting task of figuring out why the web-server (IIS) was recycling every couple of hrs and when I analyzed the Crash Dump file there it was obvious that "System.String" type objects were occupying about ~250MB in memory and probably not being released or garbage collected fast enough. While some of String objects were all greater than 85000 bytes it was stored in Gen 2 [LOH - Large Object Heap] instead of Gen 0 and probably highly fragmented. So I decided to try to replicate same issue of my development machine so I hooked up the DebugDiag Memory leak process to my "aspnet_wp.exe" process (IIS 5.5 Windows XP) and simulated traffic using "tinyget" (Microsoft IIS Tool) to one of my test pages which performed similar string manipulation as the live page.



From above screen shot we can see that the String.Object type is ~10MB with 109894 objects in memory which looked quite a lot just to display data from DB and some simple string manipulation.

So while digging around MSDN [http://msdn.microsoft.com/en-us/library/system.string.intern.aspx], I was introduced to String.Intern method. Basically .NET creates a Intern Pool which contains a single reference to each unique literal string declared or created programmatically.

After I modified my application to use String.Intern (basically I added String.Intern in my property (get;set)) in my Business Entity class's and simulated the traffic again and created a new memory dump and following was the result:



As you can see from my above screen shot, the "string.object" memory and the number of instances have reduced to ~3.5MB and 21447 respectively when compared to ~10MB and over 100K objects. Though this string.intern has reduced the string.objects but one main drawback is the fact that the intern pool is not flushed until app recycles. This pool is global and objects in the pool remain for life of the app.

Following is a sample of my BusinessEntity Class:



Syntax: string.intern("string object" or "text")
The reason why I used "string.intern(value ?? "")" is because string.intern does not accept null values. Since I added string.intern in Getter's and Setter's, I had to make sure the value is not NULL and by default I set it to "". Also another example would be string concatenating the same data over and over again like the following example:



As you can see above that "/images/ratingBig-" is being concatenated or basically a constant value which over hear would make sense to use String.Intern to create only one instance of the global string object.

I personally feel that String.intern works wonders or atleast works for my situation but word of caution about it's global scope of intern pool objects.

Labels: ,