CODE IMPLEMENTING CACHES IN SITECORE
Recently I've been looking at implementing caches in Sitecore, and in my current project I've had to do this a few times; let's have a look at my general pattern.
I've just been caching strings; although other objects can be cached, mostly all I need are strings or, sometimes a few IDs.
First, I defined my cache class:
public class MyCache : CustomCache
{
public MyCache() : base("Example.MyCache", StringUtil.ParseSizeString(Settings.GetSetting("Example.Cache.Settings.Size", "20MB")))
{
Sitecore.Events.Event.Subscribe("publish:end", this.OnPublishEnd);
Sitecore.Events.Event.Subscribe("publish:end:remote", this.OnPublishEnd);
}
protected virtual void OnPublishEnd(object sender, System.EventArgs eventArgs)
{
this.Clear();
}
new public void SetString(string key, string value)
{
base.SetString(key, value);
}
new public string GetString(string key)
{
return base.GetString(key);
}
}
And then I defined a class, using the singleton pattern, to instantiate and manage that cache.
public static class CacheManager
{
private static readonly MyCache _myCache;
static CacheManager()
{
_myCache = new MyCache();
}
public static string GetMyCache(string key)
{
return _myCache.GetString(key);
}
public static void SetMyCache(string key, string value)
{
_myCache.SetString(key, value);
}
}
And that's it - which was all pretty painless.
Points to note:
You have to register your cache class to receive (and handle) publishing:end events. Otherwise it will not automatically clear when items are published. Yeah, I know, I'm not convinced I like that either; it certainly came as a surprise.
It does only handle strings. You can cache objects - but then you need to estimate the size of the objects, and it all starts to get a bit more complicated.
I'm not sure I like having to use reflection just to put something into a cache...You can just use the .NET cache - but then you have to do something to clear the cache on events like publishing end. Ben Golden has also described that here in his PublishingCacheDependency. I think that this is the route I'd go for caching objects, rather than simple strings; you don't need to estimate the object size with the ASP.NET cache, and the PublishingCacheDependency
References:
How to create a custom cache in Sitecore by Anders Laub
Sitecore’s CustomCache – A simple implementation by Max Slabyak
Is reading the web config faster than Sitecore's Cache?
Okay, I'll admit, I felt I knew the answer to this - but after my work with the CustomCache object, I felt that this was an interesting experiment.
If I just need to read string, is it faster to read from the configuration file with Sitecore.Configuration.Settings.GetSetting() or using the cache?
Well, the short answer is that the file is roughly twice as fast. Good, no cache needed!
I found that for the below code, on my machine, the 'reading file' loop took about 1800ms, but the 'reading cache' loop took about 3600ms. There was some variation in the results - of the order of about 15% - but reading from the file was always faster. Good!
My test code:
string exampleValue = Sitecore.Configuration.Settings.GetSetting("example");
string key = "test";
int iterations = 10000000;
CacheManager.SetSettingsCache(key, exampleValue);
Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int i = 0; i < iterations;="" i++)="" {="" string="" x="Sitecore.Configuration.Settings.GetSetting("example");" }="" sw1.stop();="" stopwatch="" sw2="new" stopwatch();="" sw2.start();="" for="" (int="" j="0;" j="">< iterations;="" j++)="" {="" string="" y="CacheManager.GetSettingsCache(key);" }="">