8

Vorrei misurare il tempo di rendering di un'applicazione JSF. A causa delle mie ragioni di potere, l'applicazione non può essere popolata con i registri.Misurare il tempo di rendering di una vista JSF dopo una richiesta del server

Pertanto, la mia domanda sarebbe: esiste un modo in cui posso misurare il tempo di rendering dell'applicazione dopo aver eseguito una determinata azione che include una chiamata di back-end (server) utilizzando un browser qualsiasi?

Finora, dopo aver utilizzato gli Strumenti per sviluppatori di Chrome, ho individuato quanto segue. Nella scheda Rete, ogni richiesta ha il "Tempo" visualizzato. Inoltre, dopo aver selezionato una determinata voce, nella scheda "Temporizzazione", viene visualizzata una visualizzazione più dettagliata. Ora, posso dire da ciò che "Waiting" è stato catturato il round-trip sul server, ma per quanto riguarda il tempo di rendering effettivo.

Supponendo che l'intera richiesta abbia richiesto 1 sec e che la sezione in attesa sia di 500 ms, è possibile dedurre che il rendering è 1sec-500ms? Presumo di no, ecco perché sto facendo questa domanda.

Per farla breve, avrei bisogno di sapere dal browser, per una certa richiesta, quanto tempo era l'elaborazione del server e per quanto tempo era il rendering dell'interfaccia utente effettivo.

Qualsiasi consiglio sarebbe molto apprezzato. Grazie.

risposta

10

che si può fare con un costume ViewDeclarationLanguage cui si misura il createView(), buildView(), renderView() e, se necessario restoreView() metodi.

Ecco un esempio kickoff:

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; 
    } 

} 

Per farlo funzionare, creare la fabbrica di seguito:

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; 
    } 

} 

e registrarlo come di seguito in faces-config.xml:

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

Il createView() è la fase di creazione dell'istanza di ba UIViewRoot concreta sed su <f:view> e <f:metadata> presenti nei file di visualizzazione. Quando si utilizza Facelets (XHTML) come vista, durante questo passaggio tutti i file XHTML associati verranno analizzati dal parser SAX e memorizzati nella cache per un periodo definito in javax.faces.FACELETS_REFRESH_PERIOD. Quindi può accadere che sia una volta relativamente lento e l'altra volta veloce.

Il buildView() è il passo del popolamento dell'albero dei componenti JSF (getChildren() di UIViewRoot) in base alla composizione della vista (XHTML). Durante questo passaggio, vengono eseguiti tutti i taghandler (JSTL e amici) e vengono valutate tutte le espressioni EL in questi taghandler e negli attributi id e binding del componente (per i dettagli, vedere anche JSTL in JSF2 Facelets... makes sense?). Quindi, se i bean di backing vengono creati per la prima volta durante il tempo di creazione delle viste e invocando la business logic durante lo @PostConstruct, può accadere che ciò richieda molto tempo.

Il renderView() è il passo per generare l'output HTML in base all'albero del componente JSF e al modello, a partire da UIViewRoot#encodeAll(). Quindi, se i bean di backing sono costruiti per la prima volta durante il tempo di rendering della vista e invocando la business logic durante lo @PostConstruct, allora potrebbe succedere che ciò richieda molto tempo.

Se i bean di supporto non eseguono correttamente la business logic nei metodi getter anziché in @PostConstruct o in qualsiasi altro listener di eventi del ciclo di vita che si verifichi una sola volta, è possibile che ciò richieda ancora più tempo. Vedi anche Why JSF calls getters multiple times.

+0

Questo è semplicemente ... fantastico. Grazie! – user2271933

+0

Prego. – BalusC

+0

[ViewDeclarationLanguageWrapper] (http://docs.oracle.com/javaee/7/api/javax/faces/view/ViewDeclarationLanguageWrapper.html) è stato aggiunto in 2.2. Pensi che sarebbe facile modificarlo per funzionare con 2.1 o sarebbe meglio cercare un altro modo per implementarlo? –