No speed improvement when using Ehcache with Hibernate
I have no speed improvement when using Ehcache with Hibernate
Here are the results I get when I run the test below. The test reads 80 Stop objects and then the same 80 Stop objects using the cache.
On the second reading, it hits the cache, but there is no speed improvement. Any idea on what I am doing wrong?
Speed Test:
First Read: Reading stops 1-80 : 288ms
Second Read: Reading stops 1-80 : 275ms
Cache Info:
elementsInMemory: 79
elementsInMemoryStore: 79
elementsInDiskStore: 0
JunitCacheTest
public class JunitCacheTest extends TestCase {
static Cache stopCache;
public void testCache()
{
ApplicationContext context = new ClassPathXmlApplicationContext("beans-hibernate.xml");
StopDao stopDao = (StopDao) context.getBean("stopDao");
CacheManager manager = new CacheManager();
stopCache = (Cache) manager.getCache("ie.dataStructure.Stop.Stop");
//First Read
for (int i=1; i<80;i++)
{
Stop toStop = stopDao.findById(i);
}
//Second Read
for (int i=1; i<80;i++)
{
Stop toStop = stopDao.findById(i);
}
System.out.println("elementsInMemory " + stopCache.getSize());
System.out.println("elementsInMemoryStore " + stopCache.getMemoryStoreSize());
System.out.println("elementsInDiskStore " + stopCache.getDiskStoreSize());
}
public static Cache getStopCache() {
return stopCache;
}
}
HibernateStopDao
@Repository("stopDao")
public class HibernateStopDao implements StopDao {
private SessionFactory sessionFactory;
@Transactional(readOnly = true)
public Stop findById(int stopId) {
Cache stopCache = JunitCacheTest.getStopCache();
Element cacheResult = stopCache.get(stopId);
if (cacheResult != null){
return (Stop) cacheResult.getValue();
}
else{
Stop result =(Stop) sessionFactory.getCurrentSession().get(Stop.class, stopId);
Element element = new Element(result.getStopID(),result);
stopCache.put(element);
return result;
}
}
}
ehcache.xml
<cache name="ie.dataStructure.Stop.Stop"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="5200"
timeToLiveSeconds="5200"
overflowToDisk="true">
</cache>
stop.hbm.xml
<class name="ie.dataStructure.Stop.Stop" table="stops" catalog="hibernate3" mutable="false" >
<cache usage="read-only"/>
<comment></comment>
<id name="stopID" type="int">
<column name="STOPID" />
<generator class="assigned" />
</id>
<property name="coordinateID" type="int">
<column name="COORDINATEID" not-null="true">
<comment></comment>
</column>
</property>
<property name="routeID" type="int">
<column name="ROUTEID" not-null="true">
<comment></comment>
</column>
</property>
</class>
Stop
public class Stop implements Comparable<Stop>, Serializable {
private static final long serialVersionUID = 7823769092342311103L;
private Integer stopID;
private int routeID;
private int coordinateID;
}
a source to share
The first error I see is that you are handling the cache on top of the Hibernate second level cache, which will already cache the objects Stop
. It's just useless, the second level cache is transparent, you don't need to add additional classes (like Element
here) or additional code. So the DAO method should be:
@Transactional(readOnly = true)
public Stop findById(int stopId) {
return (Stop) sessionFactory.getCurrentSession().get(Stop.class, stopId);
}
And that's all, nothing else. Again, second level activation is declarative, you don't need to change your code.
Second error: your current test will not actually hit the second level cache, the second loop uses the same session and will get objects from ... the session (first level cache), not from the second level cache. If you want to test the second level cache use another session (i.e. close the first one and get another one from the factory session).
I would recommend activating category logging org.hibernate.cache
to log all L2 cache activity and make sure everything is working as expected.
Once you are sure, remove the logging and rerun your (fixed) test on a larger sample (x10 or x100).
a source to share
Hibernate will use the second level cache automatically when you add an item <cache>
to the mapping file. You don't need to explicitly manage the cache before / after retrieving objects from the session.
Have you tried with a lot of objects? Benchmarks for a second are not very reliable.
a source to share