During my evaluation of highly scalable technologies I incurred in some performance problems with the EJB3 implementation. It seems to me that it is a quite common problem
Yesterday I was getting very dissappointing results from the benchmarks of the EJB3 implementation of the sample application. I have discovered some nice hints for optimizing Hybernate and EJB3 applications and a very good video on EJB3. This hepled me understand why my EJBs were not updated properly, but most of all why I was getting such poor performance.
The performance problem was due to the use of eager fetching on a many to many relationship. The relationship in question was friendship between users. This is a many to many relationship with itself. This means eager fetching is propagated transitively, so each time I loaded a user, all the friends were loaded as well, and also the friends of the friends and the friends of… basically the whole table.
By default many to many relationships use lazy fetching, but I changed this to eager when I wrote the application. The reason I had eager fetching on this relationship is that when I tried to get the number of friends a user had, my appserver was complaining that it couldn’t be done with lazy fetching. My error was in performing this through user.getFriends().size(). What I’m doing now instead is asking the database to give me the number of friends by using a query like “SELECT count(f) FROM user u JOIN u.friends f WHERE…”.
After that I changed some transaction attributes so that read only operations do not require transactions. Given the semantic of the methods I don’t require a strong level on consistency, so it’s relatively safe to do this. This minimizes delays due to contention and increases the paralellizability (try pronouncing this aloud) of the applications.
The result was that now my application runs 10 times faster. Now I’m getting 79 requests per second if I run the server on an EC2 instance and the client on my machine. This is just a little slower than the 100 requests per second obtained by the pojo in memoty solution, which means that EJB3 is pretty fast. I still have to test this without the communication bottleneck to be sure of the actual performance.