JSF: choice between legacy components and fashionable performance killers
This blog post was originated due to performance issues in one big web application. Everybody optimizes Java code, but it seems nobody try to optimize the JavaScript code. Strange, because on the client-side there is much room for improvements. I would state, even more than on the server-side. We will analyse the perfomance of editable JSF standard components, sometimes called “legacy”, and modern PrimeFaces components with rich JavaScript widgets. This is a neutral analyse, without to blame any library or any person. Only facts.
Well. What do we want to test? The goal is to measure the client-side perfomance (without backend logic) of JS script block executions for PrimeFaces
p:inputText /p:selectOneMenu. We want to test an editable p:dataTable with inputs /
selects components in table cells. The table has 25 rows and 16 columns, that means 25 * 16 = 400 cells. Every cell contains either an input or a select component. There are 6 test cases. Standard h:inputText and h:selectOneMenu don’t have JS script blocks, so it is interesting to see what for impact JS widgets have.
The entire test project is available on GitHub. Simple clone or download it and run with built-in Maven Jetty plugin. The page load speed is measured with the new Navigation Timing JavaScript API for accurately measuring performance on the web. The API provides a simple way to get accurate and detailed timing statistics. It’s more precise than using JS Date object. The Navigation Timing JavaScript API is available in Internet Explorer 9 and higher, last versions of Google Chrome and Firefox. The code to measure the time after the current response has been arrived until the window onload event is fired is shown on the GitHub.
JavaScript is single-threaded, so let’s see how sequential script block executions can slow down displaying a web page. If we only test
h:inputText and p:inputText, the difference is marginal. The page load time is almost the same. Running on Windows 7 and Firefox 20.0.1 I could only see that the table with p:inputText needs ca. 200-300 ms more than the table with h:inputText. This is a good result which means the JS script execution for one p:inputText takes less than 1 ms. Really good. Congrats to PrimeFaces. A mix test with inputs and selects shown that the page with PrimeFaces components takes approximately 1.5 sek. more than the page with standard components. Adding more PrimeFaces select components slows the page rendering time down. Extreme case is to have only p:selectOneMenu components. This is a perfomance killer and the reason why our web application was too slow. Internet Explorer shows the well-known error message “A script on this page is causing Internet Explorer to run slowly”. Take a look at page load time self.
Running on Windows 7 and Firefox 20.0.1
h:selectOneMenu
p:selectOneMenu
If we assume that component renderers take approximately the same time to render HTML output, we can calculate the time for JS script block execution of a single p:selectOneMenu. This time is 11,3 ms. That’s too much. The reason may be many inefficient jQuery selectors in widget’s constructor. I don’t know and it doesn’t matter here. On my notebook with Ubuntu, I got a huge time difference ca. 10 sek. The browser with 400 p:selectOneMenu tags almost “freezes”.
Running on Kubuntu 12.04 and Firefox 20.0
h:selectOneMenu
Conclusion
Some people say “JSF is slow, JSF is not a right technology”. Wrong. JSF is fast enough. It depends on how to use this framework. Editing of everything at once is nice, but obviously it is not recommended to use a large editable DataTable with rich JSF components. What would be an alternative for editable DataTable? There are many ways, depending on individual preferences. I will try to propose some ones.
- Use standard JSF select components in large editable tables. But what is with theming? No problem. All modern browser, also IE8 and higher allow to style native HTML select elements. You can adjust colors for borders, background and let selects look more or less stylish according to applied theme. Presupposed is of course, you don’t need advanced features such as custom content within select components (filter functionality or whatever).
- Cell editing feature in PrimeFaces renders native select elements and it is fast.
- Row editing feature in PrimeFaces renders native select elements and it seems to be also fast.
- Master-Detail approach in one view. You select a row and see details to edit. Details can be shown outside of the table – on the right side or at the top, depending on table’s width / height.
- Master-Detail approach with separate views. You select a row and switch the views. Instead of table, you see details like in the MasterDetail component of PrimeFaces Extensions. From details you can go on to another levels to create / edit more details and then, at the end, jump to the overview table again.