views:

324

answers:

4
+1  Q: 

large object cache

I have a .NET2.0 C# web-app. It has a variable number of large, init-expensive objects which are shared across multiple requests but not sessioned to any given user. I therefore need to persist them in a lookup structure. These objects need to be created as required and are not required for the lifespan of the app, merely the lifespan of their usage.

Plus a bit.

The memory leaking way to do this is a simple dictionary, the memory safe way to do this is a weakreference backed dictionary, but the problem I'm having is that the GC is just too damned fast. Realistically this may not be a problem because the traffic to the objects should be such that they'll stay alive without being forced to regenerate too much, but ideally I'd like them to scale down too.

Is there some kind of middle-ground solution I'm not thinking of which will keep the objects safely hidden from the GC for a period of time X, but also allow them to be collected at the end of that time, preferably where that time counter gets reset every time they're used in a way similar to session tokens?

+1  A: 

Why don't you use the Cache object from the framework and set a sliding expiration on it. Say 10 minutes. If it is used at least once every 10 minutes it will stay in cache, if the 10 minutes elapses it will expire and GC will remove it.

An example: (I believe this is the full syntax

Cache.Add("myKey", MyLargeObject, null, DateTime.Now.AddMinutes(10), Cache.SlidingExpiration, CacheItemPriority.High)
Mitchel Sellers
+5  A: 

I'm not sure why the HttpRuntime cache would not work here. Items inserted into the cache will be "renewed" every time they are touched, thus keeping them alive until they are no longer needed; and after that they will continue to stay in cache until they expire (sliding or rolling time) or they are forced out due to memory pressure. They can also be forced out at an explicitly-set, absolute time regardless of usage:

  • Absolute time: items are forced out after the system clock passes a certain DateTime

  • Sliding (rolling) time: every time an item is touched, its countdown to death is reset. The duration of the countdown is the sliding time (for example, 5 minutes).

Example usage:

//adds itemObject to cache under name "UniqueItemKey"
//set to expire 5 minutes after last touched
HttpRuntime.Cache.Add("UniqueItemKey", 
                      itemObject, 
                      null,
                      Cache.NoAbsoluteExpiration,
                      new TimeSpan(0, 5, 0),
                      CacheItemPriority.Normal,
                      null);
Rex M
Exactly what the OP needs, I believe.
configurator
bang on - now I just have the problem of peeking without touching, but that's for another question...
annakata
A: 

It sounds like you're already describing a solution to your own problem; a kind of cache structure which holds strong references for some period of time but then downgrades them to weak references if some time passes without the object being 'accessed'.

Brian
the downgrading is the trick though...
annakata
A: 

The key part is "the lifespan of their usage." How do you define that? If you can define it precisely in a way which doesn't require knowledge of the future, the rest is probably easy.

Jon Skeet