Okay, I'm not going to go into as much depth with this evaluation simply because I don't feel like I need to.
I'll provide the simple benchmark script(same as last one,just modified to use NCache instead) at the end.
NCache installed easy enough, but I had to update my powershell to use it(still hacking on Win7 for now) since I decided not to use their 60 day full GUI interface...
Overall it's very much similar to the setup/install experience of Redis, only the windows version of it, with the usual windows type quirks...;)
The test environment is different though, NCache is running as a local service on my development machine, meaning it has full access to all 24G ram and 8 cores on my machine where-as Redis was running in a Linux VM on my machine with only 1 core and 4G of ram...
Now on to the results, initial test, 1Million writes/reads in a standard foreach through the dataset:
Just slightly better than Redis..
And then the Parallel.ForEach test:
...Slower...hmm
And then I tried the NCache InsertAsync method inside a Parallel.ForEach method(this one Redis finished writing in under 10 seconds):
Granted, there were 1million records in the db when I started that test.
So, I cleared them out and ran the test again, 88 seconds for write time, and 107 seconds for read/verify...
Memory Usage!! Redis I think topped out somewhere in the 500mb range, with multiple millions of records in the db. NCache has been using between 1.5G and 2G+ consistently with only 1M records in the db & over 2.5G with 2million. So, I ran a total of 4 tests against NCache and cleared the db 2 times, by the end of my testing the NCache service is sitting on 3.2G of memory, with 1million records in the db.
I'm not going to get too into the configuration either, I'm sure there are options that could be tuned and whatnot..
I love simplicity, I love out of the box performance, I love friendly and efficient use of memory, and so far Redis is pretty far ahead in all 3 categories.
So, what's next? Well, I need to do just a little more research and configuration testing on Redis to make sure it will hold up the way I would need it to, then I start coding again.. I may look into a distributed messaging solution like ZeroMQ as a possible augment, or alternative to the KV db as well. Still got some gears to turn here and there.
Test Script:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Alachisoft.NCache.Web.Caching;
namespace TestCache
{
class Program
{
static Dictionary<string, string> TestDataSet = new Dictionary<string, string>();
//static ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.56.101");
static Stopwatch sw = new Stopwatch();
static void Main(string[] args)
{
//Build Test Dataset
Console.Write("Building Test Data Set.");
int cnt = 0;
for (int i = 0; i < 1000000; i++)
{
cnt++;
TestDataSet.Add(Guid.NewGuid().ToString(), Guid.NewGuid().ToString());
if (cnt > 999)
{
cnt = 0;
Console.Write(i.ToString() + "_");
}
}
Console.WriteLine("Done");
string cacheID = "uwNCacheTest";
Cache csh = NCache.InitializeCache(cacheID);
sw.Start();
//Console.WriteLine("Starting 'write' Benchmark");
//foreach (KeyValuePair<string, string> kv in TestDataSet)
// {
// csh.Insert(kv.Key, kv.Value);
//}
Console.WriteLine("Starting Async Parallel 'write' Benchmark.");
Parallel.ForEach(TestDataSet, td =>
{
//db.StringSet(td.Key, td.Value);
// db.StringSetAsync(td.Key, td.Value, flags: CommandFlags.FireAndForget);
//csh.Insert(td.Key, td.Value);
csh.InsertAsync(td.Key, new CacheItem(td.Value), DSWriteOption.None, null);
});
Console.WriteLine("TIME: " + (sw.ElapsedMilliseconds / 1000).ToString());
sw.Restart();
//Console.WriteLine("Testing Read Verify.");
//foreach (KeyValuePair<string, string> kv in TestDataSet)
//{
// if (csh.Get(kv.Key) as string != kv.Value)
// {
// Console.WriteLine("Error Getting Value for Key: " + kv.Key);
// }
//}
Console.WriteLine("Testing Parallel Read Verify");
Parallel.ForEach(TestDataSet, td =>
{
//if (db.StringGet(td.Key) != td.Value)
if (csh.Get(td.Key) as string != td.Value)
{
Console.WriteLine("Error Getting Value for Key: " + td.Key);
}
});
Console.WriteLine("TIME: " + (sw.ElapsedMilliseconds / 1000).ToString());
sw.Stop();
Console.WriteLine("Press any key..");
Console.ReadKey();
}
}
}
Interesting. Thanks for sharing.