While researching the possibilities that the second level cache in nhibernate provides I tested some implementations. Currently the outcome is quite unexpected and I'am questioning if my expectations are wrong.
At first 4 * 20000 simple objects with one string property are inserted into the database then four threads are getting them by the object-id (session.Get<SimpleObj>(id)
). Each thread only accesses the ids it did create. The access-pattern is random and gets 1000 objects and then recreates the session.
while (true)
{
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
for (int i3 = 0; i3 < 1000; i3++)
{
long id = (long)ids[rnd.Next(19999)];
var t = session.Get<SimpleObject>(id);
var no = t.StringProperty;
}
Interlocked.Add(ref ops, 1000);
tx.Commit();
}
}
Results
Versions used
Is the different performance between those providers and the SysCache2 implementation to be expected?
As Frederic pointed out the testing scenario does not make too much sense as two different classes of caching architectures with two different uses cases are compared. The first class (5 & 6) can not be scaled horizontally while 1 and 2 can. Currently the SQL-Server is running on the same machine so shared-memory as an IPC-Mechanism is used, therefore i disabled all IPC Connection possibilities an configured it to use TCP/IP to connect to the database. As result the performance of the no-cache-scenario drops about 10000 op/s which brings the fastest distributed caching provider into a reasonable distance.
With the comparison of the caching providers I want to test if these providers can be used in a session-per-request setup to cache reference data like countries, currencies or balance-sheet structures. As the performance of the best performing distributed cache is still only half the op/s of the plain NHibernate version I am not sure if this is the way to go.
This is no surprise to have SysCache(2)
(or RtMemoryCache
if you try this other one too) to perform highly better than Redis
or MemCached
. The formers are in-process memory caches, their use does not incur any network IO nor any inter-process communication. The laters are distributed caches, they implies at-least inter-process communications and in most cases network IO, which incurs quite higher use cost.
There is not really any point comparing distributed caches performances to non-distributed caches performances. You should use distributed caches only if you need sharing your cache among many processes. You would not be able to use non-distributed caches if you have that requirement.
What is surprising is to have the "no cache" scenario (so, SQL queries) to perform highly better than distributed caches.
One key point is missing in your test description in my opinion: what drives the performance cost of SQL queries in your scenario? If the db server is hosted on the same physical host than the web server, this cost is fairly low compared to what it is in more usual setups. Some db solution like SQL server may even skip any network IO and go for inter-process in memory communications (through named pipes) when they are hosted on the same host than the web server.
Side note: if you do not consider configuring SysCache2
for getting invalidated through SQL Server data change notifications, you should test SysCache
instead, which is lighter. (This will probably not really change results in your test scenario though.)
The very first point is to be sure you actually need your cache to be distributed. Each process can safely have its own cache if:
Of course, data cache warm-up will be slower with non distributed caches, but if distributed cache performs too poorly, this is not a point.
If you need it to be distributed, you should then evaluate if your SQL Server is a bottleneck under load or not. If under load, your SQL Server can be a bottleneck to your application, then distributed cache will help offloading it. Otherwise, better not use them if, in your setup, distributed caches are consistently performing worse than your db server.
Side note: If only the condition (2.) is met, you may also give a try to non-distributed cache with invalidation from SQL Server notification, allowing you to avoid stale data. See here for how to configure SysCache2
for being notified by SQL Server.