How to use the GC for caching...
Consider the following situation:
- You need to do a transformation on an object, which is potentially a very expansive operation.
- The result of the transformation is needed in several locations, and you've no way to control when/how they need it. (The object reside in a repository and can be requested by anyone).
- You want to use caching, but afraid of causing memory leaks or starting to get into trouble with expiration policies and managing the cache. (And you don't want / can't use Asp.Net's Cache).
What do you do?
I just had a situation like that, I needed to do a transformation on a object so I could run various rules on it (rules are my life recently ;-) ), the rules usually need some sort of a second graph to run over, which is pretty expansive. I didn't want to use the Asp.Net Cache because that introduce a dependecy that I can't control, and make it hard to test stuff. In addition, while hundreds of rule may require the result of the trasformation, it's only going to live for a relatively short period of time, in this case, caching would really be a waste of time.
The solution? Make the object its own cache, and rely on the GC cleaning up after you. Here is the implementation:
internal interface IExpensiveObjectHolder
{
ExpensiveObject ExpensiveObject { get; set; }
}
public class ObjectGraph : IExpensiveObjectHolder
{
ExpensiveObject expensive;
ExpensiveObject IExpensiveObjectHolder.ExpensiveObject
{
get{ return expensive; }
set{ expensive = value; }
}
}
public class Transformer
{
public ExpensiveObject Transform(ObjectGraph objGraph)
{
IExpensiveObjectHolder holder = (IExpensiveObjectHolder) objGraph;
if(holder.ExpensiveObject!=null)
holder.ExpesiveObject = ExpensiveTransformation(objGraph);
return holder.ExpesiveObject;
}
}
Users of the class sees nothing, but the object is created once and only once, potentially saving quite a lot. Of course, you need to measure first, and you may run into problems where the object that request the cached object change it, which cause problem to other objects. If it's easier to clone the object than to create it, than it's one way to go.
Comments
Comment preview