8

JSFアプリケーションのレンダリング時間を測定したいと思います。私の力の理由から、アプリケーションにログを設定することはできません。サーバリクエスト後にJSFビューのレンダリング時間を測定する

したがって、私の質問は次のようになり、私は任意のブラウザを使用してバックエンド(サーバー)の呼び出しを含んでいる特定のアクションを実行した後、アプリケーションのレンダリング時間を計測することが可能な方法はありますか?

これまでChrome Developer Toolsを使用した後、私は次のことを見つけました。 [ネットワーク]タブでは、各要求に[時刻]が表示されます。さらに、特定のエントリを選択した後、[タイミング]タブで、より詳細な視覚化が表示されます。 ここからは、サーバーへのラウンドトリップがここでキャプチャされた "待機中"が表示されますが、実際のレンダリング時間はどのようなものかわかります。

全体の要求は1秒を取って、それは500msのだ待機部と仮定すると、私はレンダリングが、それは1秒、500ミリ秒だと控除することができますか?私はそうは思わない、なぜこの質問をしているのか。

かいつまんで、私は、サーバーの処理だったとどのくらい実際のUIレンダリングしたどのくらいの特定の要求のために、ブラウザから知っている必要があります。

ヒントをいただければ幸いです。ありがとうございました。

答えて

10

カスタムViewDeclarationLanguageあなたがcreateView()を測定することにより、buildView()renderView()および必要に応じrestoreView()方法であればであることを行うことができます。

ここでキックオフの例です:

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

} 

それは、実行以下の工場作成するために取得するには:

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

} 

をそしてfaces-config.xmlで以下のように登録:

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

createView()は、コンクリートを作成するステップですUIViewRootインスタンスbaビューファイルに<f:view><f:metadata>があります。 Facelets(XHTML)をビューとして使用する場合、このステップではすべての関連するXHTMLファイルがSAXパーサーによって解析され、javax.faces.FACELETS_REFRESH_PERIODで定義されている時間キャッシュされます。だから、それは比較的ゆっくりとした1つの時間であり、他の時間は急速に激しくなることがあります。

buildView()は、ビュー(XHTML)の構成に基づいてJSFコンポーネントツリー(getChildren()UIViewRoot)を入力するステップです。このステップの間、全てのtaghandlers(JSTLや友人は)(詳細は、またJSTL in JSF2 Facelets... makes sense?を参照)が実行されており、それらのtaghandlersとコンポーネントのidbinding属性のすべてのEL式が評価されます。したがって、ビューの作成時に初めてバッキングBeanを構築し、@PostConstructの間にビジネスロジックを呼び出すと、時間がかかることがあります。

renderView()UIViewRoot#encodeAll()始まる、JSFコンポーネント・ツリーとモデルに基づいてHTML出力を生成するステップです。したがって、レンダリング時間中に初めてバッキングBeanを構築し、@PostConstructの間にビジネスロジックを呼び出すと、時間がかかることがあります。またはその他の1回発生のライフサイクル・イベント・リスナーではなく、バッター・ビーンがゲッター・メソッドでビジネス・ロジックを誤って実行している場合、これはさらに時間がかかることがあります。 Why JSF calls getters multiple timesも参照してください。

+0

これはちょうど...素晴らしいです。ありがとうございました! – user2271933

+0

よろしくお願いいたします。 – BalusC

+0

[ViewDeclarationLanguageWrapper](http://docs.oracle.com/javaee/7/api/javax/faces/view/ViewDeclarationLanguageWrapper.html)が2.2に追加されました。あなたはこれを2.1で動作するように変更するのは簡単でしょうか、それを実装する別の方法を探す方が良いでしょうか? –

関連する問題