Friday, August 15, 2008

Hibernate read-only cache strategy bug?

Hibernate has several cache stratagies, and one of them is ReadOnly. It looks like ReadOnly should be one which provides the best performance, which is also mentioned in Hibernate Reference. But just have a quick look at code of get method of that strategy:

public synchronized Object get(Object key, long timestamp) throws CacheException {
Object result = cache.get(key);
if ( result!=null && log.isDebugEnabled() )
log.debug("Cache hit: " + key);
return result;

That method is syncronized, which doesn't looks like good performance sign. Basicaly it is bottleneck specially for systems which require high-performance cache reading operations. I suppose, cache implementation itself has to take care about syncronisation stuff and stratgy shouldn't apply such strict restrictions. So it looks like obviouse bug.
Also, it blocks you from using of such feature like non-blocking loading if expired cache entries, which allows to serve the old content to subsequent threads until the cache entry has been updated.
NHibernate developers were also suprized with that syncronization and finaly have decided to remove it. See details here.
Regading to Java developers, as workaround, they can use NonstrictReadWriteCache strategy, which doesn't have syncronization and looks like suitable alternative for ReadOnly for the most cases.


phil pirj said...

Unfortunately, I don't see a better solution to that since java 1.5 and below doesn't have a separate read/write synchronization mechanisms. And H still should support that. There should definitely be a JVM-specific strategy implemented, so that pre-1.6 JVMs continue to suck with all-CPU wait for one, while 1.6+ can read the cache whether there was no changes to it.

Is there any better solution?
We committed a couple of H related patches to 3.2.1 during development of a product with <10mb storage via H. I wonder how people with 100Gb DBs work with their DBs via H. Science fiction or at least related

phil pirj said...

...and who t f needs this timestamp after all?

Stas said...

Mechanism existed before, but it wasn't part of standard java, it was library created by Doug Lee. And actually even with java.concurrent.* there is nothing new in JVM itself, that's just a library.

I suppose that solution here is remove syncronized and let cache think about concurrent access.

Timestamp is required for isolation purposes, e.g. in ReadWriteCache.

Blogger said...

If you are looking into making money from your websites with popunder advertisments, you can try one of the biggest companies - Pop Cash.