Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Performance problem when switching from pure Hibernate

  1. #1
    Join Date
    Sep 2004
    Location
    Berlin, Germany
    Posts
    8

    Default Performance problem when switching from pure Hibernate

    Hi,

    I'm currently in the process of switching my persistence layer from pure Hibernate to Spring+Hibernate. That means instead of constructing the SessionFactory myself I let Spring do the configuration. My DAO implementation uses HibernateDaoSupport.

    Now the problem is: a single saveOrUpdate(object) that took about 500 ms now needs more than 9 seconds. The data are the same, the mapping is the same, Hibernate's configuration should be the same (copied and adapted from hibernate.cfg.xml to applicationContext.xml).

    I'm clueless what the reason for this performance problem is and where to look for a solution.

    Any hints are welcome,
    Oliver

  2. #2
    Join Date
    Aug 2004
    Location
    Melbourne, Australia
    Posts
    1,104

    Default

    Spring shouldn't affect Hibernate's performance. Can you isolate the code and post it.

  3. #3
    Join Date
    Aug 2004
    Location
    Southampton, UK
    Posts
    826

    Default

    Oliver,

    This does sound quite bizarre. However, you might want to check whether you are using the same datasource configuration. You should also investigate the P6Spy tool to see whether both versions of the application are actually executing the same SQL.

    Post back with you findings.

    Rob

  4. #4
    Join Date
    Sep 2004
    Location
    Berlin, Germany
    Posts
    8

    Default

    Hmm, having show_sql set to true displays subtle differences. But the overall amount of SQL queries is nearly the same.

    The point is: without Spring the SQL log shows up very fast, with Spring I can nearly watch each query one after another.

    Regarding the DataSource:
    (note: this is currently a non-web standalone test)

    In hibernate.cfg.xml:
    Code:
          <session-factory>
             <property name="hibernate.dialect"
                >net.sf.hibernate.dialect.MySQLDialect</property>
             <property name="hibernate.connection.driver_class"
                >com.mysql.jdbc.Driver</property>
             <property name="hibernate.connection.url"
               >jdbc&#58;mysql&#58;//141.***&#58;3306/myDB?relaxAutoCommit=true</property>
             <property name="hibernate.connection.username">xxx</property>
             <property name="hibernate.connection.password">xxx</property>
    
            ...
    In applicationContext.xml:
    Code:
       <bean id="myDataSource" 
             class="org.springframework.jdbc.datasource.DriverManagerDataSource">
          <property name="driverClassName">
             <value>com.mysql.jdbc.Driver</value>
          </property>
          <property name="url">
             <value>jdbc&#58;mysql&#58;//141.***&#58;3306/myDB?relaxAutoCommit=true</value>
          </property>
          <property name="username">
             <value>xxx</value>
          </property>
          <property name="password">
             <value>xxx</value>
          </property>
       </bean>
       
       <!-- Hibernate SessionFactory -->
       <bean id="mySessionFactory" 
          class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
          <property name="dataSource">
             <ref local="myDataSource"/>
          </property>
          <property name="hibernateProperties">
             <props>
                <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.connection.pool_size">1</prop>
                <!-- etc other properties -->
    
                 ...
    
       <bean id="objectDAO" class="MyDAOImpl">
          <property name="sessionFactory">
             <ref bean="mySessionFactory" />
          </property>
       </bean>
    
    ...
    Well, the Java code isn't any spectacular (both in main(String[] a))
    formerly:
    Code:
            Session s = MyHibernateHelper.currentSession&#40;&#41;;
            Transaction tx = s.beginTransaction&#40;&#41;;
            try &#123;
                s.saveOrUpdate&#40;o&#41;;
                tx.commit&#40;&#41;;
            &#125;
            catch &#40;HibernateException e&#41; &#123;
                tx.rollback&#40;&#41;;
            &#125;
            MyHibernateHelper.closeSession&#40;&#41;;
    Now:
    Code:
            SessionFactory sessionFactory = 
                &#40;SessionFactory&#41;MyDAOHelper.getBean&#40;"mySessionFactory"&#41;;
            Session s = SessionFactoryUtils.getSession&#40;sessionFactory, true&#41;;
            myDAO = &#40;MyDAO&#41;MyDAOHelper.getBean&#40;"objectDAO"&#41;;
            myDAO.save&#40;o&#41;;
            s.flush&#40;&#41;;
            SessionFactoryUtils.closeSessionIfNecessary&#40;s, sessionFactory&#41;;
    
         and in MyDAOImpl.save&#40;o&#41;&#58;
    
            getHibernateTemplate&#40;&#41;.saveOrUpdate&#40;o&#41;;
    I think this is all standard code.
    (Sorry for the length of this reply)

    I'm going to check P6Spy in any case, thanks.
    Oliver

  5. #5
    Join Date
    Aug 2004
    Posts
    1,110

    Default

    I would start by switching to a different data source - org.springframework.jdbc.datasource.DriverManagerD ataSource is more geared for testing and it does not do any connection pooling. Try using Commons DBCP or C3P0 pooled connection data source. If you want to run a quick test - use org.springframework.jdbc.datasource.SingleConnecti onDataSource - it keeps a connection open for the length of its life or until destroy() is called on it.
    Thomas Risberg
    SpringSource by Pivotal
    http://www.springsource.org

  6. #6
    Join Date
    Sep 2004
    Location
    Berlin, Germany
    Posts
    8

    Default

    Quote Originally Posted by trisberg
    Try using Commons DBCP or C3P0 pooled connection data source. If you want to run a quick test - use org.springframework.jdbc.datasource.SingleConnecti onDataSource - it keeps a connection open for the length of its life or until destroy() is called on it.
    Hi Thomas,
    unfortunately this doesn't change anything.
    org.springframework.jdbc.datasource.SingleConnecti onDataSource refused to work for me ("connection was closed"), and org.apache.commons.dbcp.BasicDataSource results in the same performance.

    Is there anything that happens between the single SQL statements in Spring? Can I trace this by some means?

    Oliver

  7. #7
    Join Date
    Sep 2004
    Location
    Berlin, Germany
    Posts
    8

    Default

    addendum:
    I got org.springframework.jdbc.datasource.SingleConnecti onDataSource working by adding
    <property name="suppressClose"><value>true</value></property>
    but again, no change in the performance.

  8. #8
    Join Date
    Aug 2004
    Location
    Toronto, Canada
    Posts
    736

    Default

    What is the lifetime of the appcontext this is all coming out of? You are not by any chance recreating the entire appcontext (including the expensive to create SessionFactory) on each usage of the DAO, are you?
    Colin Sampaleanu
    SpringSource - http://www.springsource.com

  9. #9
    Join Date
    Sep 2004
    Location
    Berlin, Germany
    Posts
    8

    Default

    No, the appcontext is created only once.

    I guess it must have something to do with the way hibernate will be configured. I've transfered the entries of hibernate.cfg.xml to applicationContext.xml in the following way:

    Code:
       <bean id="mySessionFactory" 
          class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
          <property name="dataSource">
             <ref local="myDataSource"/>
          </property>
          <property name="mappingResources">
             <list> ... </list>
          </property>
          <property name="hibernateProperties">
             <props>
                <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.connection.pool_size">1</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.query.substitutions"
                   >true 1, false 0, yes 'Y', no 'N'</prop>
             
                <!-- JDBC -->
                <prop key="hibernate.jdbc.batch_size">0</prop>
                <prop key="hibernate.jdbc.batch_versioned_data">true</prop>
                <prop key="hibernate.jdbc.use_streams_for_binary">true</prop>
             
                <prop key="hibernate.max_fetch_depth">1</prop>
             
                <!-- Second level cache -->
                <prop key="hibernate.cache.region_prefix"
                   >hibernate.test</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.cache.provider_class"
                   >net.sf.hibernate.cache.EhCacheProvider</prop>
             </props>
          </property>
       </bean>
    However, setting Hibernate's logging to debug, I see these lines in my original configuration (using Hibernate only with hibernate.cfg.xml):

    Code:
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.connection.pool_size=1
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.show_sql=true
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.query.substitutions=true 1, false 0, yes 'Y', no 'N'
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.jdbc.batch_size=0
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.jdbc.batch_versioned_data=true
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.jdbc.use_streams_for_binary=true
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.max_fetch_depth=1
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.cache.region_prefix=hibernate.test
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.cache.use_query_cache=true
    DEBUG  net.sf.hibernate.cfg.Configuration.addProperties&#40;Configuration.java&#58;853&#41; - hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
    These lines don't appear if I use Hibernate via Spring.

    Is this probably a Hibernate issue and should be asked on the Hibernate forum?

    Oliver
    (obviously a newbie to all this stuff)

  10. #10
    Join Date
    Aug 2004
    Location
    Toronto, Canada
    Posts
    736

    Default

    If your code is working fine outside of Spring then this is Spring specific to the extent that I think your actual config or environment is messed up in Spring somehow. Spring is just a wrapper over HIbernate, so the same setup should run with the same speed, but in your case something is different.

    W/regards to the logging statements you mention, it's nothing to worry about. In the case of hibernate parsing the hibernate.cfg.xml file, it logs each property it reads from the file. In the case of feeding them in via Spring, Spring just calls Hibernate's Configuration object's addProperties method, which doesn't log all the properties. Even with Spring you could just point it (via the configLocation property) to a hibernate.cfg.xml file if you wanted, and you would see the logging...

    I'm sort of stumped here as I haven't seen anything like this before, and as I said, all Spring is doing is wrapping... Are you sure btw than in the Spring case your entire app is not running slowly for some reason (i.e. you have some thread or something consuming most resources)?
    Colin Sampaleanu
    SpringSource - http://www.springsource.com

Similar Threads

  1. Replies: 5
    Last Post: Dec 27th, 2005, 07:00 AM
  2. Replies: 1
    Last Post: Jul 5th, 2005, 03:48 AM
  3. Replies: 9
    Last Post: Dec 8th, 2004, 03:12 PM
  4. Replies: 3
    Last Post: Nov 19th, 2004, 07:16 PM
  5. Replies: 5
    Last Post: Aug 27th, 2004, 07:13 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •