EJB perfomance problem

Discussions

EJB programming & troubleshooting: EJB perfomance problem

  1. EJB perfomance problem (7 messages)

    Hi EJB gurus,

    I have a question that concerns the perfomance of the EJB technology.

    I have made a generic BMP entity bean that uses data access object to access
    records in the database. The home interface contains "Collection findAll()
    throws..." method that returns all the records from the database. It does
    return the records, but it takes some 2-3 seconds for server to complete the
    request for one client, that seems too slow for Pentium III 700 Mhz 128 MB
    RAM with SCSI HDDs. The same request implemented with JDBC works very fast.
    Is there any way to improve the perfomance?

    Threaded Messages (7)

  2. EJB perfomance problem[ Go to top ]

    What app. server do you use? Your application server may call findByPrimaryKey for each record in seach result, or even ejbLoad(). Usually you can say your server not to do it using some server-specific way.

    BTW, do you <b>really<b> need findAll method in your Entity bean? Maybe it would be better to have Session bean which access database through JDBC, converts data to some format (XML?) and returns it to client?

    Moreover, possibly the client of your bean do not need all data at once, but only a part of it (something like "search results from record 1 to record 20").
  3. EJB perfomance problem[ Go to top ]

    Thank you for your prompt reply, Stanislav.

    The appserver i use is orion-1.3.8-stable
    (http://www.orionserver.com), and it currently is run under Windows 2000. The database server is PostgreSQL 7.0.2 on Linux.

    >>Moreover, possibly the client of your bean do not need >>all data at once, but only a part of it (something >>like "search results from record 1 to record 20").

    The findAll() method has been added simply for testing purposes. Other finder methods, it seems, work the same way, the difference is only in search criteria, right?

    I use a data access object to wrap my JDBC calls. The getDAO() methods below indicate where my Bean calls the DAO.

    As the debug session shows, the appserver calls are:

    setEntityContext()
    ejbFindAll()
    getDAO()
    ejbActivate()
    ejbLoad()
    getDAO()
    setEntityContext()
    ejbFindAll()
    getDAO()
    ejbActivate()
    ejbLoad()
    getDAO()
    ...the same goes for every record...
    This piece of code is done fast.

    Then, however, it twice(!) calles ejbStore() for every database record, which (probably) appeares to be the bottleneck:

    ejbStore()
    getDAO()
    ejbStore()
    getDAO()...

    The client to my beans is a JSP. Will perfomance change if i use a SessionBean between JSP and entity EJB?
    Do you mean i have to use SessionBeans to access data for reading, and EntityBeans for reading/writing and transactions?

  4. EJB perfomance problem[ Go to top ]

    Your "ejbFindAll" method returns a collection with primary keys (1000 rows -> 1000 keys), right?

    For every key the container will call ejbLoad wich will make a "select ... from table where key = key..."

    For 1000 objects you will get 1001 calls.

    It looks like a bug but it is by design.

    To get better performance you can try CMP and to get very god performance you can throw your entity beans away and use a single select statement from within a session bean.
  5. EJB perfomance problem[ Go to top ]

    Ok, that sounds reasonable. But why does the container call ejbStore after the "select" operator? Why does it call it twice for each record? Is it a container-specific feature?
  6. EJB perfomance problem[ Go to top ]

    Don´t know, sorry.
  7. EJB perfomance problem[ Go to top ]

    Seems that you call two methods with TX_REQUIRED attribute from your JSP page. Don't know about Orion, but WebLogic container by default calls ejbLoad() at the beginning of every transaction and ejbStore() at the end of every transaction. To prevent calls of ejbLoad() WebLogic uses container-specific parameter "is-db-shared". To prevent unnecessary calls of ejbStore() isModified() method is used.

    I think that Orions supports isModified() method. But if it does not and you use BMP, you may get the same result using the boolean flag. You need to set isDirty=true in all methods that really modify your data. Then in ejbStore() you write something like
    if(isDirty) {
      // save to database
    } else {
      // nothing to do
    }

    WBR,
      Stanislav Markin
      Brainbench MVP for Java 1
      http://www.brainbench.com
  8. EJB perfomance problem[ Go to top ]

    I am no guru and in my department we just started with J2EE so my suggestions may not be the best way to do. Anyway I tell you what we thought and try to do:

    We differentiate between the following tasks:
    1) Displaying Lists of Objects
    2) Displaying/Editing Simple Objects
    3) Displaying/Editing Complex or Multiple Objects

    We only use Entity Beans (CMP) in a standard way for task #2.

    For Task #1 we use Stateless Session Beans that just return a Vector of simple Objects containing just the needed Data. The Implementation may be simple and fast - just a JDBC call.

    For any editing we use Entity Beans to get the benefits of a properly defined object model on the server.

    In case of Task #3 the instantiation of all the Entity Beans can be very slow because there are much more SQL calls done than necessary. So we use Bean Managed Persistence and as far as reading is concerned we don´t make JDBC calls but get the data from a hand-written Cache-object responsible for reading data from the database in an effective way.
    The Problem now is: how does the cache know, what data will be needed? I think, this depends mostly on the business process and for high performance it is an illusion to have this done automatically. Some processes need a lot of objects, others just some. So we introduce a interface layer of business processes (Session Beans). Every method (business process) first tells the cache which and how much data to load, then instantiates the needed entity beans (which load the data from the recently filled cache) and returns the bean reference to the client.
    Another performance issue ist, that you should not use the bean reference on the client side to call multiple get/set-methods as each call goes across the network. To solve this problem we simply use the AccessBeans with CopyHelper VAJ offers to generate.

    Finally I should mention that I don´t know yet, if this is performing well enough. We just write a small prototype to figure out.