I’m getting no improvement in speed when using Ehcache with Hibernate
Here are the results I get when i run the test below. The test is reading 80 Stop objects and then the same 80 Stop objects again using the cache.
On the second read it is hitting the cache, but there is no improvement in speed. Any idea’s on what I’m 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;
}
The first mistake I see is that you are handling a cache on top of Hibernate’s second level cache that will be already caching
Stopentities. That’s just useless, the second level cache is transparent, you don’t need to add extra classes (likeElementhere) or extra code. So the DAO method should be:And that’s all, nothing more. I repeat: activating second level is declarative, you don’t need to modify your code.
Second mistake: your current test won’t actually hit the second level cache, the second loop uses the same Session and will get objects from… the Session (the 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 session factory).
I’d recommend to activate logging on the category
org.hibernate.cacheto log all second-level cache activity and make sure things are working as expected.Once sure, remove logging and rerun your (fixed) test on a bigger sample (x10 or x100).