Cache your common string

Think of the following scenario:
Your application consist out of many grid result pages that come from different SQL statements and your application is extensible (everything is configuration base),
The XML that represent a grid results is:
<ArrayOfArrayOfColumn>
  <ArrayOfColumn>
    <Column Name=""
                   SortExpression=""
                   HeaderName=""
                   SortOrder="" />
  </ArrayOfColumn>
</ArrayOfArrayOfColumn>

It consist out of 3 classes:

  1. GridResults
  2. GridResult
  3. Column (the only place needed to change)

You might already see that most of the string properties of a column are widely used and will be the same for all the users.

When you deserialize the value into memory you actually create numerous new strings although most of them are the same - as a result you waste memory.

There are couple of thing you can do to fix this bug - One of them is to create a typed column and thus use the common properties as a part of the class but that would mean you have to make lots of changes and sometimes your application requires that each user defines his own properties.

Another option that you can use (which I think is adhoc with the most ROI) is to override the setter of the string properties to get the string out of a new StringCache class (simple string dictionary as a singleton).

Using this method you make sure that a string will only be in memory once because when deserializing process occur every property is being set of the string value that is actually being fetched from the StringCache object as a result you use the same string reference.

I have created a sample XML file, when deserializing it without using StringCache object the held memory was approx 20K

Without using StringCache

But when taking advantage of the StringCache the held memory was reduced to approx 5k

Without using StringCache

That's 75% reduce of memory

All because you have similar string in your object modal (That happens a lot)

The StringCache class as a Bypass property only to enable you to see the difference in a running application.

This is not the final solution and you might also want to change the StringCache to limit the number of Items / use WeakReference.

If you have any suggestion / fixes please comment me on that.

The profiling was done using JetBrains profiler

Cache your common string Cache your common string Reviewed by Ran Davidovitz on 12:20 AM Rating: 5

2 comments:

Anonymous said...

The common language runtime conserves string storage by maintaining a table, called the intern pool, that contains a single reference to each unique literal string declared or created programmatically in your program. Consequently, an instance of a literal string with a particular value only exists once in the system.

Did you consider to use String.Intern in you StringCache class in the following way?

public static string Fetch(string o)
{
if (Bypass)
return o;

return string.Intern(o);
}

Yan.

Ran Davidovitz said...

You are correct, i will update my post.

Thanks for posting.

Powered by Blogger.