These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Memory Consumption of list() vs. List with ScrollableResult
PostPosted: Fri May 30, 2008 5:43 am 
Newbie

Joined: Sun Dec 30, 2007 1:08 pm
Posts: 14
Hi, I've written a small test to measure the memory consumption of my Hibernate code. It seem that getting a List of objects with the list() method of a Query uses much more memory than creating the List manually by using a ScrollableResult.

The ScrollableResult memory consumption is almost identical to the consumption of a pure JDBC implementation. The list() memory consumption needs much more MB. In my case with my Database 50.000 Object need approximately 13 MB with ScrollableResult and 23 MB with list()!!

Can anybody explain this behaviour? Is my code wrong?

Hibernate Version: 3.2.2ga
Windows XP SP2
Database: Oracel 10g

Testcode:
Note: You have to replace the HQL Query with your Hibernate Objects!


Code:

public class HibernateMemoryConsumptionTest extends TestCase {

   private int size = 50000;

   private int repeats = 2;

   private boolean trackMemoryConsumption = true;

   private Runtime runtime;

   protected void setUp() throws Exception {
      super.setUp();
      runtime = Runtime.getRuntime();
   }

   protected void tearDown() throws Exception {
      super.tearDown();
      runtime = null;
   }

   public void testHibernateWithOneSession() {
      // init
      HibernateUtil.getSessionFactory();
      long heap1 = 0;
      long heap2 = 0;

      long start = System.currentTimeMillis();

      StatelessSession session = null;
      Transaction tx = null;
      List results = null;
      try {
         session = HibernateUtil.getSessionFactory().openStatelessSession();

         for (int i = 0; i < repeats; i++) {
            if (trackMemoryConsumption) {
               System.err
                     .println("Note: Memory measurement can influence time measurement!");
               runGC();
               heap1 = usedMemory(); // Take a before heap snapshot
            }

            tx = session.beginTransaction();
            Query query = session
                  .createQuery("FROM Cashflow ");
            query.setFirstResult(1);
            query.setMaxResults(size);
            results = query.list();
            tx.commit();

            assertEquals(size, results.size());

            if (trackMemoryConsumption) {
               heap2 = usedMemory(); // Take an after heap snapshot:
               final long heapsizeDiff = heap2 - heap1;
               System.out.println("'before' heap: " + heap1
                     + ", 'after' heap: " + heap2);
               System.out.println("heap delta: " + heapsizeDiff / 1024d
                     / 1024d + " MB");
            }

            results = null;

            runGC();// aufräumen für nächste schleife

         }
      } catch (Throwable t) {
         t.printStackTrace();
         if (tx != null) {
            tx.rollback();
         }
         throw new PersistenceException(t);
      }

      long end = System.currentTimeMillis();

      System.out.println("runtime with list() "
            + repeats + " repeats with " + size + " Cashflows = "
            + ((end - start) / (double) repeats));
   }

   public void testHibernateWithScrollableResult() {
      // init wird nicht mitgezählt!
      HibernateUtil.getSessionFactory();
      long heap1 = 0;
      long heap2 = 0;

      long start = System.currentTimeMillis();

      StatelessSession session = null;
      Transaction tx = null;
      ScrollableResults results = null;
      List cashFlows = null;
      try {
         session = HibernateUtil.getSessionFactory().openStatelessSession();

         for (int i = 0; i < repeats; i++) {
            cashFlows = new ArrayList();
            if (trackMemoryConsumption) {
               System.err.println("Note: Memory measurement can influence time measurement!");
               runGC();
               heap1 = usedMemory(); // Take a before heap snapshot
            }

            tx = session.beginTransaction();
            Query query = session
                  .createQuery("FROM Cashflow ");
            query.setFirstResult(1);
            query.setMaxResults(size);

            results = query.scroll(ScrollMode.FORWARD_ONLY);

            while (results.next()) {
               cashFlows.add(results.get(0));
            }
            tx.commit();

            assertEquals(size, cashFlows.size());

            if (trackMemoryConsumption) {
               heap2 = usedMemory(); // Take an after heap snapshot:
               final long heapsizeDiff = heap2 - heap1;
               System.out.println("'before' heap: " + heap1
                     + ", 'after' heap: " + heap2);
               System.out.println("heap delta: " + heapsizeDiff / 1024d
                     / 1024d + " MB");
            }

            results = null;
            cashFlows = null;

            runGC();// aufräumen für nächste schleife

         }
      } catch (Throwable t) {
         t.printStackTrace();
         if (tx != null) {
            tx.rollback();
         }
         throw new PersistenceException(t);
      }

      long end = System.currentTimeMillis();

      System.out.println("runtime with ScrollableResults "
            + repeats + " repeats with " + size + " Cashflows = "
            + ((end - start) / (double) repeats));
   }

   private void runGC() throws Exception {
      // It helps to call Runtime.gc()
      // using several method calls:
      for (int r = 0; r < 4; ++r)
         _runGC();
   }

   private void _runGC() throws Exception {
      long usedMem1 = usedMemory(), usedMem2 = Long.MAX_VALUE;
      for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i) {
         runtime.runFinalization();
         runtime.gc();
         Thread.currentThread().yield();

         usedMem2 = usedMem1;
         usedMem1 = usedMemory();
      }
   }

   private long usedMemory() {
      return runtime.totalMemory() - runtime.freeMemory();
   }
}


Last edited by Allesmallachen on Sun Jun 01, 2008 6:26 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 01, 2008 6:22 pm 
Newbie

Joined: Sun Dec 30, 2007 1:08 pm
Posts: 14
I tested this code again with a different Oracle database and a different Hibernate version (3.2.5.ga). Again the same memory problem. I will test it with a MySQL DB as soon as I have some spare time. Maybe its an Oracle problem?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.