When is a cache not really a cache

I spent a large portion of the day inside of the Caching Application Block.  Specifically, a colleague and I were tracking down what appeared to be a nasty threading bug caused by having the creation of two different cached objects that were related to one another.  As it turned out, the bug that existed couldn't explain away all of the behaviors that we observed.

As it turns out, there was what appears to be a poorly documented aspect of the Caching Application Block that was causing us grief.  The problem is that the default number of objects that the cache can store before scavenging begins is set very low.  Specifically, it is set to 5.  As well, there is a UtilizationForScavenging setting (by default, it is 80) that lowers this number ever more.  Once the cache contains the (maximum * utilization / 100) items, the scavenger starts to remove the excess items from the cache, trying to keep the number of items below the calculated value.  With the default values, this means that no more than 3 elements will be saved in the cache at a time.  The scavenging class uses a least recently used algorithm, however if you're using an absolute time expiration, there is no 'last used' information saved.  So the scavenger appears to remove the last added item. 

That's right.  Unless you make some changes to the default config, only three elements are kept in the cache.  Probably not the performance enhancer that you were looking for from a cache.  Fortunately, the values can easily be changed.  The can be found in the ScavengingInfo tag in app.config. And there is no reason not to set the maximum value much higher, as there is no allocations performed until actual items are cached. It was just the initial surprise (and subsequent fallout) that caused me to, once again, question how closely related the parents of the designers were.  But only for a moment. ;)

As one further word of warning, if there is no ScavengingInfo tag in the config class, then the default class (the same LruScavenging class just described) is used. And instead of getting the maximum cache information from the config file, a file called CacheManagerText.resx is used.  In that file, the entries called RES_MaxCacheStorageSize and RES_CacheUtilizationToScavenge are used to determine how many items to keep in the cache.  Out of the box, these values are set to the same 5 and 80 that the config file contains.