hibernate scroll 和 list

原文:https://forum.hibernate.org/viewtopic.php?p=2386803





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();
   }
}

你可能感兴趣的:(Hibernate)