↓ Skip to main content

Performance comparison: JSP + JDBC vs JSF + JPA

·728 words·4 mins
Sergii Zolotarov
Author
Sergii Zolotarov
Twenty years of Java, from Kyiv to Leeuwarden. Currently at Booking.com

I understand that performance comparison of “low-level” vs “high-level” technologies is rather unfair, but I will, as I’ve been astonished with how much performance we sacrifice to rapid development using JPA and JSF.

Our team has got a task of making a web page where one could browse through up to 10000 database records simultaneously. We failed to convince our customer that he simply does not need that much on one page. We offered various paging/filtering solutions which would display more specific information, but the customer wanted just that - all 10000 records on one page. Ok we said, let’s do it. Here I’ll describe what we came up with.

The first solution was straightforward. We used JPA and JSF. Under Weblogic 10 JPA implementation is Kodo (or OpenJPA). The page which was to display the results, contained one big table of 5-6 columns, and the data displayed belonged to 2 separate tables. JPA suggests using EAGER and LAZY fetch strategies for injecting entity dependencies. LAZY is not our choise as we need all the records at once. As for the EAGER fetch, it appeared to be a simple select. It means that after selecting 10000 records we have 10000 more selects - one per each record to select its child. This is what I disliked about JPA most of all, Hibernate for example, has a JOIN fetch type, which allows the framework to generate a select with a join to fetch child entity.

The table was rendered using JSF , sorting was implemented by hand, because sorting 10000 records in memory (which the component does), performs poorly. At last we have made it, measured throughput with JMeter - the system handles up to 30 requests per minute. When the number of users grows to 3 and over the server crashes with OutOfMemory exception. And that’s no wonder :) tons of redundant objects are generated all over the way - both in persistence and presentation layer, and they cannot be garbage collected until the request is completely rendered. All in all the customer was quite surprised with performance and we have got an optimization task. At first we suspected that JPA was the bottleneck. More specifically, we suspected that 10000 subselects were the problem. I rewrote the select using native sql query with explicit join and used @SqlResultSetMapping to map sql resultset to pojos. A very useful feature, which makes JPA not a pure ORM tool, but also a sort of resultset mapper, much like iBATIS (though iBATIS is much simpler and performant). Then we measured performance again. Pure performance gain on persistence layer was about 15%, not much. Then we started profiling JSF, and it appeared that this beast eats his lion’s share of CPU and memory. We have decided to place the table inside an iframe, the results would be rendered by a JSP page. Select is performed using pure JDBC/SQL. The controller - the servlet - handles request parameters like sorting columns, filter parameters, etc. makes a query and puts the results Iterator to requestScope, which allows iterating the resultset in an OOP fashion - returning a POJO for each row. The object instance returned is always the same, it is just filled with new data every time the next object is requested. By using this little trick we managed to avoid GC pauses - no extra objects were created during query processing. After quering the database a JSP is included in request (I used JSTL, to avoid scriptlets), connection to the database is closed when the result has been completely rendered. The results exceeded our expectations. Performance gain achieved was more than 20 times! We even did not measure memory consumption gains, as they were obvious. I must admit that complexity of the solution has increased, however MVC pattern was preserved, - we used controller (servlet), model (though it was tied to persistence layer), and view (JSP page). But the result was worth the trouble. Afterwards we redesigned another heavy part of the application also using servlet/jsp/jdbc, the rest was left as it was, for small amounts of data JPA/JSF work reasonably fast and complex form processing is really simpler. But in case you need to display something very big and do it fast, the old school JSPs + JDBC are still the best choice.


First published on the old anydoby.com blog on 2007-07-06.