Profiling nhibernate: UpdateTimestampsCache and ReadWriteCache

108 views
Skip to first unread message

somdoron

unread,
Jan 4, 2012, 12:19:22 PM1/4/12
to nhusers
We profiled our system with ANTS with the source of nhibernate 3.2 and
spring .net, we found out that the following nhiberate classes are
causing performance issues:
ReadWriteCache
UpdateTimestampsCache

both have a lock that lock the object instance for almost all methods,
for the UpdateTimestampsCache we changed the lock to be
readerwriterlockslim, for the ReadWriteCache we switched to
NonstrictReadWriteCache for the time, we are running some thread
simultensaly that all threads are doing the same workflow, so the
locks hit alot.

the question is, why UpdateTimestampsCache didn't used reader writer
lock slim from the beginning, is it safe to change it to reader writer
lock or am i missing something?
same question for the ReadWriteCache.

thanks.

Scooletz

unread,
Jan 5, 2012, 12:33:20 AM1/5/12
to nhusers
Hi,
That's interesting. The method which way the bottleneck was
Monitor.Enter? There was nothing more to optimize, like batching
queries, etc?
In the majority of cases reducing number of db calls is a better
direction for optimization.

Speaking about two classes you mentioned, AFAIK UpdateTimestampsCache
doesn't have a lock inside (I've checked it with ILSpy), it simply
wraps a given instance of ICache.
Choosing between NonstrictReadWriteCache and ReadWriteCache should not
be based on the performance. With NonstrictReadWriteCache you can get
dirty writes to your cache, as it doesn't check timestamps during put
operation. NonstrictReadWriteCache should be used iff there is almost
0 probability (it never equals 0 :)) for the write collision.

Hope it helps a bit :)

regards

somdoron

unread,
Jan 5, 2012, 8:47:48 AM1/5/12
to nhusers
Hi,

UpdateTimestampsCache has a lock on each method, it's using the
[MethodImpl(MethodImplOptions.Synchronized)] attribute on each method,
which lock the object instance (this).

Regarding the ReadWriteCache, i changed to Nonstrick only when it's
the right answer (small amount of changes vs a lot of queries)

Using the cache i'm almost not hitting the database anymore, after
changing the UpdateTimestampsCache to reader writer lock my
performance are much better.

anyway the problem with readwritecache is that if two different
threads (or more) are trying to get an object from the cache (same
type of object) they cannot do it simultaneously and need to wait for
the other to complete the fetch, although they both only read.

same for UpdateTimestampsCache, it two threads are trying to get the
timestamp of a table they cannot do this simultaneously and need to
wait for completion of the other thread.

what is the reason for using lock and not reader writer lock? was this
intentionally? is there any problem to convert this to reader writer
lock?

Thanks

Scooletz

unread,
Jan 8, 2012, 3:27:03 AM1/8/12
to nhusers
Hello again,
yep, I missed the attribute. Sorry

Even with small number of changes, you can get the collision;)

I was thinking about the lock-based-problem with the
UpdateTimestampsCache. If you cache a really heavy queries than the
lock can hurt your performance a lot. If we're speakig about switching
to RWL for locking ontoUpdateTimestampsCache's methods:
- Invalidate - should be write-locked
- PreInvalidate - should be write-locked
- IsUpToDate - should be read-locked

I see no problem with switching to RWL, but...

One more thing/tip about profiling and performance of queries. If
performance is an issue and only some subset of entities properties is
used, please do projection. If the projection is applied on the query,
NHibernate caches tuples from the result. It gives only one hit to the
query cache, retriving all the needed data to hydratize the result.
When you query against an entity, with no projection, you can get
SELECT N+1 problem on your cache (the result of the query is cached as
an array of entities identifiers; entities must be fetched
separately). So if you query only for a simple flag
(ShouldBeAcceptedByManager) or sth like that - do projection (Select)
before ToList.

take care
Reply all
Reply to author
Forward
0 new messages