-->
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.  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Hibernate & JBoss prerformance issue
PostPosted: Fri Oct 14, 2005 9:35 am 
Beginner
Beginner

Joined: Fri Oct 07, 2005 5:35 am
Posts: 38
Location: France
Hibernate version:3.1rc JBoss4.0.3

I have very strange problem of performance.

I have a stateless session bean. Its job is to retrieve some objects (more than 5000 in some extrem cases) and then to perform some queries. I have identify several problem of performance.

Problem 1: The first part of my session bean consist to retieve objects from db using the find methods of EntityManager. Objects are just loaded in memory, they are not modified. To retrieve 5000 objects from DB, it takes about 4s outside of JBoss and the same code executed in JBoss takes about 8s. It seems that all my hibernate code is much slower when executed in JBoss.

Problem2: After retireving objects(that have not been modified), I need to perform a query. When getSingleResult method is invoked on my query, query is prepared and an auto flush is performed by hibernate. Objects have only be read but their Status is to MANAGED, consequently all the objects are flushed (even if they have not been modified). In my case due to the flush query takes about 0,2s outside and JBoss and about 0.9s in JBoss.

That's 2 differents problem:
- All seems to be longer when executed in JBoss
- When executed queries flush objects and as their state is MANAGED (even if not modified), it is time consumming when a lot of objects have be resolved in the current transaction


Do someone already meet that problems ?

Is their other workarounds that resolving just a few objects in one transaction (I can not do that since that the job of my alogrithm to consult datas to perform an interpretation) ?

Any suggestion or good practice are welcome !


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 9:34 am 
Expert
Expert

Joined: Sat Oct 25, 2003 8:49 am
Posts: 490
Location: Vrhnika, Slovenia
Mark the method with @FlushMode(FlushModeType.NEVER).
Or set the flush mode by 'hand'.

Code:
                org.hibernate.FlushMode fm = session.getFlushMode();
                try {
                    session.setFlushMode(org.hibernate.FlushMode.NEVER);
                    ...
                } finally {
                    session.setFlushMode(fm);
                }


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 9:35 am 
Expert
Expert

Joined: Sat Oct 25, 2003 8:49 am
Posts: 490
Location: Vrhnika, Slovenia
Or maybe you can even use StatelessSession.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 1:33 pm 
Beginner
Beginner

Joined: Fri Oct 07, 2005 5:35 am
Posts: 38
Location: France
In fact in my real application, I write/read a lot of objects in the same transaction (I try to compute a complex result). I do not want to divide my transaction into several smaller transaction in order to keep the isolation for all datass used for my computation.

Algorithm contains queries including queries on objects that have not been committed yet. Consequently I need that flush will be performed. I do not want to invoke manually flush (in fact my application is written in EJB3 and flush is not in EJB3 API). Consequently setting the Flush mode to never seems not to be a solution for me.

I try the same things with a JDO implementation. I do not encouter that problem since the list of objects to flush is more selective. Only modified objects are in the flushList. With what I have seen trying to debug hibernate, all retrieved objects are flushed (even not read only objects).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 1:59 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hibernate 3.1 does implement this JDO style flag when the classes are instrumented.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 20, 2005 10:52 am 
Beginner
Beginner

Joined: Fri Oct 07, 2005 5:35 am
Posts: 38
Location: France
How to enhance byte code ? Is it a third party tools ? Where can I find some documentation about that ?

I'm very interesting trying to use instrumented byte code with EJB3.

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 20, 2005 12:34 pm 
Expert
Expert

Joined: Sat Oct 25, 2003 8:49 am
Posts: 490
Location: Vrhnika, Slovenia
http://www.hibernate.org/hib_docs/v3/re ... properties


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 20, 2005 1:59 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Note that even though the docs don't mention it, HB3.1 optimizes dirty checking when bytecode instrumentation is used. This might make the flush cycle slightly quicker.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 21, 2005 9:43 am 
Beginner
Beginner

Joined: Fri Oct 07, 2005 5:35 am
Posts: 38
Location: France
I try to instrument my byte code. Class seems to be enhanced (if I have a look to byte code I can see CGLIB stuff).
When I try to start my app with:
Code:
Ejb3Configuration conf = new Ejb3Configuration();
    conf.addProperties(loadProperties());
    conf.addAnnotatedClass(ParameterBO.class);
    EntityManagerFactory factory= conf.createEntityManagerFactory();


I have a the following exception:
Code:
Exception in thread "main" org.hibernate.MappingException: Could not determine type for: net.sf.cglib.transform.impl.InterceptFieldCallback, for columns: [org.hibernate.mapping.Column(interceptFieldCallback)]
   at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:266)
   at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:253)
   at org.hibernate.mapping.Property.isValid(Property.java:184)
   at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:371)
   at org.hibernate.mapping.RootClass.validate(RootClass.java:192)
   at org.hibernate.cfg.Configuration.validate(Configuration.java:975)
   at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1139)
   at org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:358)


I do not succed to understand what this InterceptFieldCallback. It seems to be in enhanced byte code. Any idea what's going wrong ?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 21, 2005 11:45 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Sorry this is a bug I've fixed a couple of days ago

http://opensource.atlassian.com/project ... se/ANN-133

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 21, 2005 1:15 pm 
Beginner
Beginner

Joined: Fri Oct 07, 2005 5:35 am
Posts: 38
Location: France
I tried the patch in annotations. It fixed the problem for the byte code enhancement.

Unfortunatelly it does not fix my problem with time consumming flush before query. All the objects that have been resolved in the transaction (even just read objects) have the status set to MANAGED. Consequently with or without enhance I have the same performance. Before each query all objects are flushed.

I use hibernate 3.1rc1 , entity manager 3.1 beta 4 and annotations beta6. It seems to be the last version working together for this 3 jars.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 22, 2005 12:31 am 
Newbie

Joined: Mon Nov 21, 2005 3:38 pm
Posts: 5
You can open a new session just for the purpose of reading your 5000 objects, then close that session. Once the first session is closed you can attach the objects to the transactional session if you need to.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 22, 2005 9:50 am 
Beginner
Beginner

Joined: Fri Oct 07, 2005 5:35 am
Posts: 38
Location: France
I have try to profile a little what's happen. In fact in my sample, I retrieve from DB a Protocol objects that contains a List of parameters.

Protocol ->*Parameter

None of these objects have been modified. Having a look in DefaultFlushEntityEventListener.onFlushEntity method I can see that with enhanced classes the mightBeDirty flag is turned to false (with non enhanced class it was to true). The problem comes from the list of Parameter includes in the Protocol.

In the onFlushEntity, since my protocol has collections I go through
Code:
if ( persister.hasCollections() ) {
            new FlushVisitor(session, entity).processEntityPropertyValues(values, types);
         }


Method that seems to be time consumming is FlushVisitor.processCollection. If I had at the beginning to stop the process when collections are not dirty, it divide the flush time by 2.
Code:
if (collection!=null) {
         final PersistentCollection coll;
         if ( type.hasHolder( getSession().getEntityMode() ) ) {
            coll = getSession().getPersistenceContext().getCollectionHolder(collection);
         }
         else {
            coll = (PersistentCollection) collection;
         }
//////////////////////////////////////////// MODIF ///////////
         if (!coll.isDirty()) return null;
         Collections.processReachableCollection( coll, type, owner, getSession() );
      }


With that modif, flush is still a bit longer but it is much better. Maybe I have break something ? but it seems to work. Any comment are welcome !

I will continue to profile my code to see what's is time consumming.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 22, 2005 1:51 pm 
Newbie

Joined: Mon Nov 21, 2005 3:38 pm
Posts: 5
I would be worried that the collection dirty flag just indicates whether anything has been added or removed from the collection, and is not set if the collection has the same contents but one of the contained objects has been modified.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 22, 2005 1:57 pm 
Beginner
Beginner

Joined: Fri Oct 07, 2005 5:35 am
Posts: 38
Location: France
Just some more comments. In fact my Object looks like:
Code:
@OneToMany(cascade = CascadeType.PERSIST)
  @JoinTable(table = @Table(name = "Protocol_Param"), joinColumns = { @JoinColumn(name = "relation_id") }, inverseJoinColumns = @JoinColumn(name = "position_id"))
  public List<ParameterBO> getParameters() {
    return parameters;
  }
  @OneToMany(cascade = CascadeType.PERSIST)
  @JoinTable(table = @Table(name = "Protocol_SubProtocol"), joinColumns = { @JoinColumn(name = "relation_id") }, inverseJoinColumns = @JoinColumn(name = "position_id"))
  public List<ProtocolBO> getSubProtocols() {
    return subProtocols;
  }


With more profiling, with that config, probems seems to come from collections. I retrieve 20000 protocol from DB but I never modifiy them. Before each query flush takes about 0.6s.
- If I remove my collection from mapping, flush takes only 0.01s.
- If I change the cascadetype to all it is about 1s for flush.

With profiling flush, it seems that time consuming methods in AbstractFlushingEventListener.flushEverythingToExecutionsare (sort by time consummmed):
1 - flushEntities(event)
2 - flushCollections(session)
3 - prepareEntityFlushes(session) and prepareCollectionFlushes(session)

It seems to be quite difficult to change that part of code ... Any idea ?


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

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.