Friday, June 5, 2015

.NET MemoryCache vs. Memcached vs AWS Elasticache

Setup


  • .NET 4.5.1
  • Memcached local server (Northscale)
  • AWS ElastiCache, cache.r3.2xlarge, 2 nodes
  • Using Enyim client library for Memcached
  • 10,000 Gets and Puts of string data
  • 10,000 unique keys

The results


Memory Manager GET – Total ms GET – Average ms SET – Total ms SET – Average ms
.NET MemoryCache 6.354 0.0006 3.515 0.0004
Memcached - Local Server 802.329 0.0802 761.066 0.0761
AWS ElastiCache 807.002 0.0807 763.705 0.0764

The Code

static void Main(string[] args)
{
try
{
TestAccess();
MemoryCacheTest();
MemcachedTest();
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadKey();
}
}

static List<String> GetKeys()
{
var keys = new List<String>();
for (int i = 0; i < reps; i++)
keys.Add(Guid.NewGuid().ToString());
return keys;
}

static int reps = 10000;
static void MemoryCacheTest()
{
ObjectCache cache = MemoryCache.Default;

Stopwatch sw = new Stopwatch();

List<String> keys = GetKeys();
CacheItemPolicy policy = new CacheItemPolicy() { };
sw.Start();
for (int i = 0; i< reps; i++)
{
cache.Set(keys[i], keys[i], policy);
}
sw.Stop();
ReportTiming(".NET MemoryCache SET", sw.Elapsed);

sw.Reset();

sw.Start();
for (int i = 0; i < reps; i++)
{
cache.Get(keys[i]);
}
sw.Stop();
ReportTiming(".NET MemoryCache GET", sw.Elapsed);
}

static void MemcachedTest()
{
using (MemcachedClient client = new MemcachedClient())
{
Stopwatch sw = new Stopwatch();

List<String> keys = GetKeys();
CacheItemPolicy policy = new CacheItemPolicy() { };

sw.Start();
for (int i = 0; i < reps; i++)
{
client.Store(StoreMode.Set, keys[i], keys[i]);
}
sw.Stop();

ReportTiming("MemCached SET", sw.Elapsed);

sw.Reset();

sw.Start();
for (int i = 0; i < reps; i++)
{
client.Get<String>(keys[i]);
}
sw.Stop();
ReportTiming("MemCached GET", sw.Elapsed);
}
}
static void ReportTiming(String label, TimeSpan elapsedTime)
{
Console.WriteLine("{0}: {1:N3} ms", label, elapsedTime.TotalMilliseconds);
Console.WriteLine("  Average per operation: {0:N4} ms", elapsedTime.TotalMilliseconds / reps);
}

static void TestAccess()
{
using (MemcachedClient client = new MemcachedClient())
{
var key = "LastProcessed";
var val = DateTime.Now.Ticks;
long valRetrieved;

Console.WriteLine("Storing Key: {0}, Value: {1}",
key, val);
client.Store(StoreMode.Set, key, val);

valRetrieved = client.Get<long>(key);
Console.WriteLine("Retrieved Value: {0}, Key: {1}",
valRetrieved, key);

if (val != valRetrieved)
Console.WriteLine("Memcached access FAILED");
else
Console.WriteLine("Memcached access OK");
}
}
}