String Interning: The Garbage Collectible way
Since I know people will want the actual implementation, here is a simple way of handling string interning in a way that will allow you to GC the results at some point. The issue is simple, I want to intern strings (so a string value is only held once through my entire app), but I don’t want to be stuck with them if the profiler state has been clear, for example.
public class GarbageCollectibleStringInterning
{
private static IDictionary<string,string> strings = new Dictionary<string,string>();
private static ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
public static void Clear()
{
locker.EnterWriteLock();
try
{
strings.Clear();
}
finally
{
locker.ExitWriteLock();
}
}
public static string Intern(string str)
{
string val;
locker.EnterReadLock();
try
{
if(strings.TryGetValue(str, out val))
return val;
}
finally
{
locker.ExitReadLock();
}
locker.EnterWriteLock();
try
{
if(strings.TryGetValue(str, out val))
return val;
strings.Add(str,str);
return str;
}
finally
{
locker.ExitWriteLock();
}
}
}
This is a fairly simple implementation, a more complex one may try to dynamically respond to GC notification, but I think that this would be useful enough on its own.
Using this approach, I was able to reduce used memory in the profiler by over 50%. I gave up on that approach, however, because while it may reduce the memory footprint, it doesn't actually solve the problem, only delay it.