Measure JSF view rendering time after server request

I would like to measure the rendering time of a JSF application. Due to my power reasons, the application cannot be filled with logs.

So my question is, is there any way to measure the rendering time of the application after performing a certain action that includes an internal (server) call using any browser?

So far, after using the Chrome Developer Tools, I have noticed the following. On the "Network" tab, each request has a "Time". In addition, after selecting a specific record, a more detailed visualization is displayed on the Dates tab. Now I can say from this that "Waiting", that the server is going back and forth, but what about the actual rendering time.

Assuming that the entire request took 1 second and the wait section was 500 ms, can I subtract that its rendering is 1 second-500 ms? I guess not, that's why I ask this question.

In short, I would need to find out from the browser, for a specific request, how long the server processing took and how long the real user interface rendering was.

Any advice would be greatly appreciated. Thanks.

+8
google-chrome-devtools performance-testing jsf-2 rendering
source share
1 answer

You can do this with a ViewDeclarationLanguage , in which you measure createView() , buildView() , renderView() and, if necessary, restoreView() .

Here is an example run:

 public class VdlLogger extends ViewDeclarationLanguageWrapper { private static final Logger logger = Logger.getLogger(VdlLoggerFactory.class.getName()); private ViewDeclarationLanguage wrapped; public VdlLogger(ViewDeclarationLanguage wrapped) { this.wrapped = wrapped; } @Override public UIViewRoot createView(FacesContext context, String viewId) { long start = System.nanoTime(); UIViewRoot view = super.createView(context, viewId); long end = System.nanoTime(); logger.info(String.format("create %s: %.6fms", viewId, (end - start) / 1e6)); return view; } @Override public void buildView(FacesContext context, UIViewRoot view) throws IOException { long start = System.nanoTime(); super.buildView(context, view); long end = System.nanoTime(); logger.info(String.format("build %s: %.6fms", view.getViewId(), (end - start) / 1e6)); } @Override public void renderView(FacesContext context, UIViewRoot view) throws IOException { long start = System.nanoTime(); super.renderView(context, view); long end = System.nanoTime(); logger.info(String.format("render %s: %.6fms", view.getViewId(), (end - start) / 1e6)); } @Override public ViewDeclarationLanguage getWrapped() { return wrapped; } } 

To start it, create below factory:

 public class VdlLoggerFactory extends ViewDeclarationLanguageFactory { private ViewDeclarationLanguageFactory wrapped; public VdlLoggerFactory(ViewDeclarationLanguageFactory wrapped) { this.wrapped = wrapped; } @Override public ViewDeclarationLanguage getViewDeclarationLanguage(String viewId) { return new VdlLogger(wrapped.getViewDeclarationLanguage(viewId)); } @Override public ViewDeclarationLanguageFactory getWrapped() { return wrapped; } } 

And register it as shown below in faces-config.xml :

 <factory> <view-declaration-language-factory>com.example.VdlLoggerFactory</view-declaration-language-factory> </factory> 

createView() is the step of creating a specific instance of UIViewRoot based on the <f:view> and <f:metadata> present in the view files. When using Facelets (XHTML) as the view during this step, all related XHTML files will be parsed by the SAX parser and cached for the time as defined in javax.faces.FACELETS_REFRESH_PERIOD . So it can happen that this one time is relatively slow, and another time flashes quickly.

buildView() is the stage of populating the JSF component tree ( getChildren() of UIViewRoot ) based on the composition of the view (XHTML). During this step, all tag handlers (JSTL and friends) are executed, and all EL expressions in these id and binding tag attributes and components are evaluated (for more details, see also JSTL in JSF2 Facelets ... does it make sense? ). Therefore, if beans support is built for the first time during build time and invokes business logic during @PostConstruct , then it can happen that it takes a lot of time.

renderView() is the step of generating HTML output based on the JSF component tree and model, starting with UIViewRoot#encodeAll() . Therefore, if beans support is built for the first time during visualization of the time of viewing and calling business logic during @PostConstruct , then it may happen that it takes a lot of time.

If beans support does not correctly execute business logic in getter methods instead of @PostConstruct or any other one-time lifecycle event listener, then it may happen that it consumes even more time. See Also Why JSF calls getters several times .

+10
source share

All Articles