8

Ich möchte die Renderzeit einer JSF-Anwendung messen. Aus Gründen meiner Macht kann die Anwendung nicht mit Protokollen gefüllt werden.Messen Sie die Renderzeit einer JSF-Ansicht nach einer Serveranfrage

Daher meine Frage wäre, gibt es eine Möglichkeit, in der ich die Renderzeit der Anwendung nach einer bestimmten Aktion, die einen Back-End-Aufruf (Server) mit einem beliebigen Browser enthält messen kann?

Bisher habe ich nach der Verwendung der Chrome Developer Tools folgendes entdeckt. Auf der Registerkarte "Netzwerk" wird für jede Anfrage die "Zeit" angezeigt. Außerdem wird nach der Auswahl eines bestimmten Eintrags auf der Registerkarte "Timing" eine detailliertere Visualisierung angezeigt. Nun kann ich von dem "Warten" sagen, dass die Rundreise zum Server hier festgehalten ist, aber wie sieht es mit der tatsächlichen Renderzeit aus.

Unter der Annahme, dass die gesamte Anfrage 1sek dauerte und der Warteabschnitt 500ms, kann ich ableiten, dass das Rendern die 1sec-500ms ist? Ich nehme nicht an, deshalb stelle ich diese Frage.

Lange Rede, kurzer Sinn, ich müsste aus dem Browser wissen, wie lange die Serververarbeitung dauerte und wie lange das eigentliche UI-Rendering war.

Alle Tipps würden sehr geschätzt werden. Vielen Dank.

Antwort

10

Sie können mit einem benutzerdefinierten ViewDeclarationLanguage tun, wobei Sie die createView() messen, buildView(), renderView() und ggf. restoreView() Methoden.

Hier ist ein Kick-off Beispiel:

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

} 

und registrieren Sie es wie unten in faces-config.xml:

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

Die

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

} 

Um den unten Fabrik zu erhalten zu laufen, erstellen createView() ist der Schritt zum Erstellen der Beton UIViewRoot Instanz ba sed auf <f:view> und <f:metadata> in den Ansichtsdateien vorhanden. Bei der Verwendung von Facelets (XHTML) als Ansicht werden während dieses Schritts alle zugeordneten XHTML-Dateien vom SAX-Parser analysiert und für eine Zeit zwischengespeichert, die in javax.faces.FACELETS_REFRESH_PERIOD definiert ist. So kann es passieren, dass es einmal relativ langsam und das andere Mal blitzschnell ist.

Die buildView() ist der Schritt der JSF Komponentenbaum Bevölkern (der getChildren() von UIViewRoot), basierend auf der Ansicht (XHTML) Zusammensetzung. Während dieses Schritts werden alle Taghandler (JSTL und Freunde) ausgeführt und alle EL-Ausdrücke in diesen Taghandlern und Komponenten id und binding Attribute ausgewertet (für Details, siehe auch JSTL in JSF2 Facelets... makes sense?). Wenn Backing-Beans also zum ersten Mal während der Erstellung der Ansicht erstellt werden und während die Geschäftslogik aufgerufen wird, kann dies zeitaufwendig sein.

Die renderView() ist der Schritt zum Generieren der HTML-Ausgabe basierend auf JSF-Komponentenbaum und das Modell, beginnend mit UIViewRoot#encodeAll(). Wenn Backing-Beans also zum ersten Mal während der Renderzeit der Ansicht erstellt werden und während die Geschäftslogik aufgerufen wird, kann dies zeitaufwendig sein.

Wenn Backing-Beans die Geschäftslogik in Getter-Methoden anstelle von oder einem anderen einmalig vorkommenden Lebenszyklus-Ereignis-Listener falsch ausführen, kann dies dazu führen, dass dies noch mehr Zeit in Anspruch nimmt. Siehe auch Why JSF calls getters multiple times.

+0

Das ist einfach ... großartig. Vielen Dank! – user2271933

+0

Gern geschehen. – BalusC

+0

[ViewDeclarationLanguageWrapper] (http://docs.oracle.com/javaee/7/api/javax/faces/view/ViewDeclarationLanguageWrapper.html) wurde in 2.2 hinzugefügt. Denkst du, es wäre einfach, dies zu modifizieren, um mit 2.1 zu arbeiten, oder würde ich besser nach einer anderen Möglichkeit suchen, es zu implementieren? –