Performance Zone is brought to you in partnership with:

Masoud Kalali has a software engineering degree and has been working on software development projects since 1998. He has experience with a variety of technologies (.NET, J2EE, CORBA, and COM+) on diverse platforms (Solaris, Linux, and Windows). His experience is in software architecture, design, and server-side development.

Masoud has published several articles at Java.net and Dzone. He has authored multiple refcards, published by Dzone, including but not limited to Using XML in Java, Java EE Security and GlassFish v3 refcardz. He is one of the founder members of NetBeans Dream Team and a GlassFish community spotlighted developer. Recently Masoud's new book, GlassFish Security has been published which covers GlassFish v3 security and Java EE 6 security.

Masoud's main area of research and interest includes service-oriented architecture and large scale systems' development and deployment and in his leisure time he enjoys photography, mountaineering and camping. Masoud's can be followed at his Twitter account.

Masoud has posted 82 posts at DZone. You can read more from them at their website. View Full User Profile

JPA and First Tier Application Performance Problems

09.07.2009
| 7193 views |
  • submit to reddit
I want to write about JPA, performance, caching and related things. Though it wont be very well organized, it may come useful for new JPA developers. Recently I have been assigned a task to work on performance problems of a first tier application and further extend it with some new forms and reports and address some usability glitchs in the software. The application was developed by a company which no longer exists. The developer company was dissolved before they finishing the development cycle.

The performance issue was very important for the customer, so I start investigating this problem first. First things first, I ran the application on client machine and hell it was slow, very slow indeed. It took some 15 seconds for the application to open a JFrame with two auto completing JComboboxs on it. I thought maybe it is the first time I am accessing the database and application is trying to initialize a soft client side cache. So, I closed the JFrame and opened it again. the result was almost the same. I checked network and DNS resolving was fast and no substantial network delay was in place. I thought the problem is either in poor development or something is wrong on database machine.

I asked an operator about the performance and I understand that is a data access problem, and I should focus on that area.

I opened a terminal to the database server machine and checked how much load it is taking when I open that particular JFrame, well there was no substantial load on the server. indeed there was no load on the server. I briefly check to see what kind of indexing we have on two tables where I though are used to load items of the JComboBoxes and hell, no index was created. The developers either were crazy not to have any index except for the default PK index or they had forgotten to execute their post installation script.

I asked for the source code of the application to see what is going on in the application code. The application is based on TopLink Essential which is a part of the GlassFish project, contributed by Oracle for data access. I had some previous experience with Toplink and I was sure that there is nothing wrong with the persistence provider itself.

Application source code was documented but not enough to understand the code easily. I located that JFrame form and checked how they are loading the content of JComboBoxes. Well, they were calling an static method from a DAO class which returns a list an Object named A. Then it was iterating over the list and loading the JComboBox with A.property1. I thought why on earth were they are fetching the entire object to use on property?

I checked the second JC and I found the same steps, a DAO method was called which returns a list and then the JC was loaded using D.property1.
I start looking at these two entities to see what is going on with them and I find that each of them has a one to many relation with at least one other entities. So we basically had something like:

A -----1-----N----->B------1----------N------>C
D -----1-----N----->E

There were no FetchType determined for the relationships so, Toplink assume FetchType.EAGER for the relationships by default. The FetchType.EAGER means that JPA eagerly loads all related records from database and create all corresponding objects before we even start using them.
What does that means? It Means that for the first JComboBox that client application creates num(A)+num(B)+num(C)+num(A)*num(B)*num(C) objects just to show a list of names in a JComboBox. Very funny huh?

I created a development database setup in the development environment (NetBeans works well with ANT based projects) and start changing the code. I didn't change the fetch types, instead I changed the JPA queries to ensure that I am only loading one field and not all fields which have eager fetching relationships. I compiled and the problem for this particular form were solved. I added two indexes to ensure that I am getting the result as fast as possible.

I was thinking about JPA caching and why JPA was not able to improve the overall performance after I closed the form and re-opened it. I think the data load was more than what JPA could cache by default.

I will blog more about these application and its problems. I believe it was either a prototype of the developers were intended to reiterate over the code to improve the performance.
Published at DZone with permission of its author, Masoud Kalali.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Slim Ouertani replied on Mon, 2009/09/07 - 4:24am

nice post!

but, is it more simple to change the properties for toplink to be lazy by default or try another persistance provider which is lazy by default ?

Gérald Quintana replied on Mon, 2009/09/07 - 5:43am

According to the JPA spec, @ManyToMany and @OneToMany are lazy by default whereas @ManyToOne and @OneToOne are eager by default. I find these defaults are:

  • Not consistent: @?ToMany and @?ToOne behave differently
  • Performance problem prone:  @?ToOne being eager too many relations are loaded by default

Andy Jefferson replied on Tue, 2009/09/08 - 2:25am in response to: Gérald Quintana

Exactly, so if you had a chain of 1-1 relations then all would get loaded!! One of the reasons why JDO defaults to lazy for object relations; and allows full control on fetch grouping so people can optimise performance for their application.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.