2014/07/18

XPages Toolbox を使ってみる - CPU プロファイリング編

前回から始まった XPages Toolbox シリーズの第2弾は、CPU のプロファイリングです。

XPagesToolbox.nsf をブラウザで表示したところで前回は終わりました。
このアプリケーションには「Home」以外に、
  • CPU Profiler
  • Backend Profiler
  • Runtime Monitoring
  • Session Dumps
  • Periodic Snapshots
  • Threads
  • Logging
の7つのタブがあります。早速 CPU のプロファイリングのタブを開いてみましょう。

 

CPU タイムの計測

まずここで計測できるのは、CPU タイムになります。
一般的に CPU タイムは、CPU の負荷と言い換えれば分かりやすいかもしれません。処理演算によって使用される時間を計測して、どの処理が重いのかを計測するものです。ここで少し言葉の定義ですが、
  • CPU タイム (CPU Time) は、スレッドが実行時に実際に消費した時間
  • Wall タイム (Wall Time) は、スレッドにより消費された時間で、CPU タイムに加え、スリープや待ち時間を加えた時間
 をいいます。
また、プロファイリングした結果のことをスナップショット(Snapshot)という言い方をしています。


上の画面にはいくつかボタンがありますのでその説明から。

 

ボタンの説明

  • Start CPU Time Profiler:CPU Time のプロファイリング実行開始します
  • Start Wall Time Profiler:Wall Time のプロファイリング実行開始します
  • Stop Profiler:プロファイリングを終了し、プロファイリングの結果文書を作成します。(プロファイリングを開始していない場合は、グレイアウトしてクリックできません)
  • Reset Profiler:プロファイリングで収集したデータはメモリー上に残っていますが、このボタンを押してメモリー上のデータを消去します
  • Save Snapshot:プロファイリング継続中でも、今時点のスナップショットを作成します
  • Delete Snapshots:プロファイリングの結果の文書をすべて削除します

 

プロファイリング操作

プロファイリングの操作は、以下のとおりで簡単です。
1. 「Start CPU Time Profiler」ボタンか「Start Wall Time Profiler」のいづれかをクリックして開始します。
ステータスは 「Started」に変われば、開始しています。

2. 次に実際のアプリケーションを動かします。動かす対象によって、1ページだけとか1ファンクションだけとか、一連の処理だとかによって、自分のプロファイリングしたい場所の開始から終了を動かしてみます。

3. アプリケーションの操作が終了したら、XPagesToolbox.nsf に戻ってきて、「Stop Profiler」ボタンを押し、プロファイリングを終了します。


スナップショットの見方

計測の開始から終了までは大した事はありませんが、プロファイリングの結果をどうみるかが大変です。できるだけ、分かりやすく説明したいと思いますが、見るものが違えば当然結果も違ってきますから、ここでは Mastering XPages 2nd Edition で提供されているサンプルデータベースを使って説明します。
「Chp20Ed2.nsf」をブラウザから開くと、次のページが開きます。
赤い四角で囲ったリンクをクリックします。すると下のページが表示されるので、一番上の「Run CPU Intensive Task (clocking 'CPU Time')」ボタンを押します。
 その後、処理がバックエンドで始まりますが、しばらく経過すると終了します。このボタンを押す前と押して処理が完了するまでをプロファイリングした結果は、私の環境では次のようになります。

 スナップショット文書は、プロファイリング単位に日付時刻でカテゴライズされています。
さらに、「XPages Request」で呼び出した XPage (例では /Chp20Ed2.nsf/testCPUvsWallTime.xsp) ごとにカテゴライズされています。
時間はミリ秒でカウントされます。上の例では、「INVOKE_APPLICATION 5」のJSFフェーズで9秒かかかっていることがわかります。

私の手元にあるサンプルアプリケーション以外の実際のアプリケーション(新規XPage作成、単一のDomino文書にバインド、フィールド数約300)を開いた直後のものでは、次のような結果が出ました。


 特に目立った数値はありませんが、実際のアプリケーションでは「XSP:Create view root」を最初に注目したほうが良いかもしれません。Create view root は XPage(ページ)に各コンポーネントを階層的にぶら下げてビュー(ページ)を作成するのですが、約300程度の入力コンポーネントや計算結果フィールドといった様々なコンポーネントをツリー構造としてページを構成するのに、31ミリ秒かかかったということになります。

もうひとつ、実際のアプリケーションで時間がかかると想定されるのは、「RENDER_RESPONSE 6」のフェーズです。これはフィールド数が多くなればなるほど値が大きくなるのが予想されます。
いずれにしても、ひとつのXPaegs リクエスト(ページからページまでの表示の間)に何秒という基準(たとえば3秒)を決めておいて合計の時間が超えているかを確認しながら、超えている場合には、詳細にドリルダウンしていくのが実際的ではないかと思います。

※失敗談より
プロファイリングを行い、プロファイリングを停止してスナップショットが作成されますが、次のプロファイリングを行なう前に必ず「Reset Profiler」をしてください。メモリー上に前回のデータが残っていますので、これをせずに続けてプロファイリングを行なうとスナップショットの数値が2倍、3倍となっていきますので注意してください。

その他のビュー

スナップショットの結果から特にCPU時間を取っているものだけを見る事ができるビューも用意されています。
「Hierarchical Dominators」というビューで、顕著なCPUタイムの消費を確認できます。これは、アプリケーションをずーっと動かしぱなしのプロファイリングをしたときに特に有効ではないかと思います。
その他、呼び出したカウント数、合計時間、時間がかかった順、時間÷カウント数で計算した平均時間別などのビューがあります。
一度確認してみてください。

次回は、自分の書いた SSJS コードに対しての CPUタイムを計測する方法を紹介したいと考えています。お楽しみに。





2014/07/15

XPages Toolbox を使ってみる - インストール編

OpenNTF Essentials の中に、「XPages Toolbox」というプロジェクトがあり、かねてから気になっていたんですが、触る機会がないまま放置していました。この Toolbox を使うと、XPages アプリケーションを動かしいる際の、CPU やヒープのダンプを取ったり、バックエンドの呼び出された回数を見たり、アプリケーションのパフォーマンスを調査する上で非常に役立つツールです。

XPages Toolbox を導入するとセキュリティ面で問題が発生するため、決して本番環境では使わないでくださいとの注意もされています。

プロジェクトの詳細をみると、要件に Notes/Domino 8.5.3 と記述されているので、9.0x では動かないのかなと思っていたのもあり、手を出していませんでした。
最近ふと Twitter を追っていくと Mastering XPages 2nd Edition の著者でもある方の 9.01 でも動きますというツィートに触発されて触ってみることにしました。

実際プロファイリングを行なうとわかりますが、自分が作成したアプリケーションの一連の処理を計測するのに向いていますが、開発サーバーで複数のア プリケーションを同時動かした中でのプロファイリングにはあまり向いていませんので、あくまで開発が終了した際のパフォーマンス検証という使い方が最もふ さわしいと感じました。

計測に当たっては、Windows OS の場合には、ネイティブなプロファイリングが可能ですが、他 OS は JVM 経由のプロファイリングになるため、多少誤差が生じるという注意書きもあります。

インストール関連は、他の方のブログやwikiに紹介されていますが、改めて私の方でも取り上げたいと思います。
今回私が使用するのは「XPages Toolkit 1.2」というバージョンです。
環境は自分のデスクトップ PC (VM) に Windows 32 bit 版のDomino サーバー 9.01 をたてています。

OpenNTF のプロジェクトページから、最新モジュール v1.2 をダウンロードします。
ダウンロードすると次のものが入っています。
赤枠で囲ったものが今回使用するものです。
ステップは以下の通りです。
  • XPagesProfilerAgent.jar
この jar ファイルを次の Domino サーバー上のディレクトリーへ配置します。
 <Domono実行ディレクトリー>¥xsp
例:C:\IBM\Domino\xsp
  • XspProfilerOptionsFile.txt
このテキストファイルを Domino サーバー上の実行ディレクトリー直下へ配置します。
例: C:\IBM\Domino
続いて、このテキストファイルに書かれている行を編集します。ここには、上記で配置した jar ファイルの場所を指定します。
例: -javaagent:c:/IBM/Domino/xsp/XPagesProfilerAgent.jar
  • java.policy ファイルへの行追加
Domino サーバー上の次のディレクトリーにある「java.policy」というファイルに次の行を追加します。
<Domino実行ディレクトリー>¥jvm¥lib¥security

追加する行は以下のとおりです。
grant codeBase "xspnsf://server:0/xpagestoolbox.nsf/-" {
    permission java.security.AllPermission;
};
  • notes.ini の編集
Domino サーバーの notes.ini に次の行を追加します。これは、上で説明した XspProfilerOptionsFile.txt を配置した場所を指定するパラメーターになります。
JavaOptionsFile=C:\IBM\Domino\XspProfilerOptionsFile.txt
  • XPagesToolbox.nsf
Domino サーバーのデータディレクトリーの直下にこのデータベースを配置します。(直下でないサブフォルダに配置したい場合は、java.policy で指定した場所を変更すれば良いらしいのですが、検証していません。)
この NSF では、Domino サーバー上で XPages を動作させる必要がありますので、適切な ID で署名します。テスト環境なので、Administrator の ID が良いでしょう。

これで、準備が整いました。
Domino サーバーを再始動します。
コンソール上を注意深く見ていただき、

*** Activating IBM XPages profiler agent

という表示が見られれば正常に動作を始めていることになります。

ブラウザより、「XPages Tookbox」データベースへアクセスし、次のページが表示されればすべての準備が完了です。
例:http://localhost/xpagestoolbox.nsf


次回は、実際のプロファイリングの方法をご紹介します。



2014/06/16

Notes/Domino 9.0.1 での @MailDbName

かなり古いバージョンの Notes/Domino アプリケーションを XPages 化する作業の中で、@MailDbName という @関数が多く使われていたので、XPages ではどうしようかと調査している途中でこういう記事を見つけました。

このブログによると 9.0.1 でこの関数を使用すると空の文字列が帰ってくるそうです。
SPR として取り上げられているかどうかわかりませんが、この関数を使用しているケースは充分考えられますので、9.0.1 へアップグレードする際は非互換として考慮しておいたほうが良さそうです。

http://nevermind.dk/nevermind/blog.nsf/subject/beware-@maildbname-now-returns-a-different-result-in-version-901-of-ibm-notes


2014/04/30

Masteting XPages 第2弾

XPages 開発本第2弾、「Mastering XPages: A Step-by-Step Guild to XPages Application Development and the XSP Language (2nd Edition)」、少し前までは5月15日が amazon.co.jp では発売予定としてあがっていましたが、先行してKindle版がリリースされています。

http://www.amazon.co.jp/Mastering-XPages-Step-Step-Application/dp/0133373371/

ハードカバーは現在の価格では 8,826円、一方 Kindle版では半値以下の 3,734円で販売しています。

電子書籍と実際の紙の本ではびっくりするほどお値段が違います。

会社で回し読みするような時には、当然紙の本のほうが良いわけですが、通勤時間に読むとか、休日に自宅に持ち帰って読むとか、持ち運びするのにはちょっと分厚い感じの本です。
それに、この本は英語なので、会社でどれくらい回し読みできるか甚だ疑問ということもあります。
やっぱり値段の安い電子書籍だよねぇ!といっても、読むのに必要な Kindle 端末や iPad での Kindle アプリは、大抵個人の持ち物なのでこの電子書籍を会社所有にすることが難しいかもしれません。
会社の経費で購入する場合は、はやり紙の本になるのでしょう。領収書も必要ですし。。。
私は、過去出版された XPages 関連書籍(英語)からずっと個人の Kindle 書籍として購入してきたので、自然と今回も個人購入にします。
電子書籍選択の理由はもちろん経済的理由(安いほうを選択)が一番の要因ではありますが、この本の目次を見るとそんなに新しいことがふんだんに出ているわけではなさそうなので、それもひとつの理由でもあります。

Kindle 端末として所有している WhitePaper で読むのは、コードやスクリーンショットが掲載されている部分の表示が粗いので疑問符がつきますが、iPadのアプリでは遜色なく見ることができます。Kindle 端末で気にいっているのはやはり検索ができるということでしょうか。章立てがきちんとしているので、頻繁に検索することはあまりないのですが、ちょっとした調べ物にも検索できるメリットは欠かせません。

いま、悩んでいるのは amazon.co.jp から購入するか、amazon.com から購入するか。amazon.com のアカウントもあるので、そちらから電子書籍は購入できます。amazon.com からの購入の利点は PC や Mac 版の Kindle アプリでも見ること。(amazon.co.jp へアクセスすると今日現在拒否されます。なにかの陰謀か?)

いづれにせよ、GW中にさらっと読んでしまおうと思います。





XPages の applicationScope 変数

ふと興味が湧いて、XPages のアプリケーションスコープ(applicationScope)変数について、こんなテストをしてみました。

おさらいとして、XPagesには
requestScope
viewScope
sessionScope
applicationScope
の4つのスコープ変数があります。

それぞれのライフサイクルを簡単に言うと、
requestScope はブラウザの更新ボタンあるいはXPageの完全更新(部分更新でなく)をすると使用できなくなります。このrequestScopeはページからページへパラメータを渡す際の元になる変数を格納したりします。

viewScopeはブラウザでページが再ロードされると使用できなくなります。
要は、requestScopeとviewScopeはひとつのページの中で、そのページ内のいくつかの場所で値を計算させたい場合に使用します。

sessionScope はユーザーセッションがタイムアウト(ある一定時間ブラウザでアプリを放ったらかしにして操作しない)になるまで、またはブラウザが再起動するまで有効です。典型的な使用例は、ユーザーに関する情報を格納する場合に使用されます。

最後に、applicationScopeはドミノサーバーが再スタートするまで有効、開発局面ではDomino Designer が再スタートするまで有効というのがその定義です。
今回興味を持ったのは、このapplicationScopeにファイルパスなどの固定情報を格納し、その値を使って他DBの参照をするといったケースで、このapplicationScopeが使えるかという疑問を持ったからです。
こんなコーディングを想定してみました。

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
 <xp:this.afterPageLoad><![CDATA[#{javascript:var now = new Date();
if (!requestScope.containsKey("requestVar")){
 requestScope.put("requestVar", "リクエストスコープ変数追加:" +now);
 }
if (!viewScope.containsKey("viewVar")){
 viewScope.put("viewVar", "ビュースコープ変数追加:"+now);
 }
if (!sessionScope.containsKey("sessionVar")){
 sessionScope.put("sessionVar", "セッションスコープ変数追加:"+now);
 }
if (!applicationScope.containsKey("applicationVar")){
 applicationScope.put("applicationVar", "アプリケーションスコープ変数追加:"+now);
 }
 
}]]></xp:this.afterPageLoad>
 <xp:table>
  <xp:tr>
   <xp:td>リクエストスコープ変数</xp:td>
   <xp:td>
    <xp:text escape="true" id="computedField1" value="#{javascript:requestScope.requestVar}"></xp:text>
   </xp:td>
  </xp:tr>
  <xp:tr>
   <xp:td>ビュースコープ変数</xp:td>
   <xp:td>
    <xp:text escape="true" id="computedField2" value="#{javascript:viewScope.viewVar}"></xp:text>
   </xp:td>
  </xp:tr>
  <xp:tr>
   <xp:td>セッションスコープ変数</xp:td>
   <xp:td>
    <xp:text escape="true" id="computedField3" value="#{javascript:sessionScope.sessionVar}"></xp:text>
   </xp:td>
  </xp:tr>
  <xp:tr>
   <xp:td>アプリケーションスコープ変数</xp:td>
   <xp:td>
    <xp:text escape="true" id="computedField4" value="#{javascript:applicationScope.applicationVar}"></xp:text>
   </xp:td>
  </xp:tr>
 </xp:table>
 <xp:button value="更新" id="button1" save="false" navigate="false">
  <xp:eventHandler event="onclick" submit="true" refreshMode="complete"></xp:eventHandler>
 </xp:button>
 <xp:button value="再ロード" id="button2">
  
 <xp:eventHandler event="onclick" submit="true" refreshMode="complete">
  <xp:this.action><![CDATA[#{javascript:context.reloadPage()}]]></xp:this.action>
 </xp:eventHandler></xp:button>
</xp:view>

上記のコードの例では、applicationScopeのライフサイクルが本番環境ではドミノサーバーを再起動しないと使えないとなると、applictionScopeを使ってアプリケーションの参照パスを定義していた場合など、ドミノサーバーの変更なしでは以前のapplicationScopeの値を持ち続けるため、困ったことになりはしないかということです。

いちいち applicationScope に何を格納しているのか、コードレビューをしないといけないのはちょっと辛いです。

ドミノサーバー、またはDomino Designer を再起動する以外にapplicationScopeを一旦リセットする方法はないか、試しに設計の置換による変更を試してみました。
そうしたら、なんと予想どおり設計の置換でこのapplicationScopeをリセットすることがきました。
これで、本番稼働中にapplicationScopeの値をリセットしたい場合、設計の置換でサーバーを再起動することなくできそうです。今回はDomino Designer のみの環境で行いましたが、結局Domino Designer のHTTPを再起動するのとドミノサーバーのHTTPを再起動することは同じであろうということでサーバーでは試していません。もし、必要があればみなさんのほうでも確認してみてください。