Last week I had to review an hibernate powered application due to his poor performance and various instability issues.
In my post Don’t Get Caught Hibernating, I’ve assumed that jdbc connectivity and caching were properly configured.
Well in fact this is not always the case.
Don’t use Hibernate built-in connection pool
Hibernate’s own connection pooling algorithm is, however, quite rudimentary. It is intended to help you get started and is not intended for use in a production system, or even for performance testing. You should use a third party pool for best performance and stability. Just replace the hibernate.connection.pool_size property with connection pool specific settings. This will turn off Hibernate’s internal pool. For example, you might like to use c3p0.
Strangely hibernate log this at info level (not warning) when instantiating the session factory
log.info("Using Hibernate built-in connection pool (not for production use!)");
Instead of using this ‘naive’ implementation, you should configure the session factory to use one of the better javax.sql.DataSource implementation :
- C3P0: add the extra hibernate.c3p0.* properties and that’s it !
- commons-dbcp : perhaps the older implementation, need to adjust the dependencies depending the java version your are using.
- tomcat7-jdbc : simpler implementation than commons-dbcp and contains more features😉
Note also that other implementations are available.
Don’t forget to
- tune the datasource pool size to fit your production needs
- choose and configure the validation mechanism for opened connections and various strategies testOnBorrow, testWhileIdle,…
- specify the isolation level : it will take the default which is sometimes too high like “repeatable read”
- specify also timeouts, max connection age
- enable preparedStatement cache
As you review your database connection pooling, it may be easy to also instrument it with jamon datasource.
You will gain visibility in your various jdbc accesses. This can also help to identify the ideal pool size (take a look at MaxActive and AvgActive)
Don’t use Hibernate default cache implementation
From hibernate documentation:
Hashtable (not intended for production use) org.hibernate.cache.HashtableCacheProvider memory
The HashtableCacheProvider isn’t a production ready implementation :
- no max size
- no invalidation (lru,…)
- no time to live, time-idle
and can be :
- considered as a memory leak,
- source of OutOfMemoryError,
- out of date data : caches not aware of changes made to the persistent store by another application
As the documentation states, various implementation exists.
From my experience Ehcache is quite easy to setup and ready to scale (cluster).
Don’t forget to disable its phone home mechanism