Posted by kalali
on September 3, 2009 at 1:24 PM PDT
I am tasked to check some performance and usability problems in a swing-jpa-mysql application. I a trying to write down what some of these experience here in a series of blog entries.
Well, this is the second time I am using the new blogging platform of Java.net. This time it was much easier and with less hurdle.
I want to write about JPA, performance, caching and related things. Though it wont be very well organized but it may come useful for new JPA developers. recently I have 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 glitch in the software. The application was developed by a company which no longer exists. The developer company was dissolved before they finishing the development cycles.
The performance issue was very important for the customer, so I start investigating the performance problem first. First things first, I run 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 JCombobox on it. I though 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 open 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 a 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 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 JComboBox/se and hell, No index was created. The developers either was crazy not to have any index except for the default PK index or they have 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 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 locate that JFrame form and checked how they are loading the content of JCombobox/es. 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 of. I though why on earth they are fetching the entire object to use on property?
I checked the second JC and I found the same steps, A DAO method were 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:
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 hu?
I create a development database setup 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 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.