cbnanashi@GAE/Jに対してprecompilationを有効にした結果、アプリケーションの起動時間(spin up時間)は多少短くなりましたが、まだ不満が残ります。さらなる起動時間の短縮のため、いろいろと試行錯誤してみました。

 なお、それぞれの個別の対策の効果はしっかり分析したわけではなく、少ない実行結果からの推測ですのでご容赦ください。

対策その1・DatastoreへのアクセスをJDOからLow Level APIにする

 いままでJDOを使用していたDatastoreへのアクセスをLow Level APIに全面的に書き換えました。

 しかしながら起動時間に関しては、数回の起動を試しましたがほとんど改善されませんでした。

 Googleのドキュメントや各種ブログの情報によると、PersistenceManagerFactoryの初期化には時間が掛かるとのことでしたので、改善に期待していましたが当てが外れました。未確認ですが、precompilationをすでにtrueにしていたため効果が出なかったのかもしれません。

 ただ、Low Level APIは思ったよりも使いやすいです。JDOに比べてエンティティの状態や、プロパティのlazy loadingなどを考慮しなくてもよい分、単純です。MemcacheにもDatastoreから取得したEntityオブジェクトをそのまま格納できます。反面、DatastoreのEntityとオブジェクト属性のマッピングを自前で行う必要がありますが、面倒くささとしてはJDBCを直接使うのと大差ありません。

 ちなみに、JDOからの移行に当たってはデータの保存を忘れることがあり、そこだけ注意が必要でした(JDOは永続化済みのオブジェクトは属性を変更するだけで保存されるため)。

対策その2・Strutsの使用を中止する

 Strutsはそれほど重いフレームワークではありませんが、起動時に設定ファイルを読んで初期化を行うためそれなりに時間が掛かっていると思われます。そこでStrutsの機能のうちアプリで使っている部分だけを抽出し、Action/ActionForm/JSPにほぼ影響が出ないようにしつつ、フルスクラッチで書き直しました(ごく一部の機能だけしか使っていないので高々25クラス位です)。struts-config.xmlに設定を書くのではなく、ソースファイル内にコードとして設定を記述するようにしました。

 結果としては、やはり大きな改善はなかったようです。

 単純なServlet+JSPのアプリは起動時間が短いため、初期化処理の削減とファイル読み込みを無くすことによる効果は、かなりあるだろうと踏んでいたのですが、こちらも残念でした。

対策その3・初期化時のクラスローディングを減らす

 初期化処理を減らしても遅いため、どうもクラスローディングが遅いのではないかと当たりをつけました。

 書き直したStrutsは、初期化時にすべてのAction/ActionFormクラスをロードする(Classオブジェクトを読み込む)作りになっていました。それを、必要となった時点でロードするように書き換えました。ちなみにコードにはpathを比較するif文がずらりと並んでいます。

 この対策は有効で、ある程度の改善が図れました。

 Google App Engine for Javaで起動時間を短縮するにはクラスローディングを減らすのが有効なようです。

対策した結果

 上記3つの対策を施し、詳細は省略しますが約50回の起動で、最小3693ms、最大14303ms、平均6884msとなりました。対策前(平均8895ms)と比較すると2000ms程度の改善です。

 またcpu_msは対策前の9385cpu_msから4363cpu_msへと半減しています。

 GAEを意識しないフレームワークではアプリ起動時に初期化を行うものが多いですし、いまさらServlet+JSPだけで開発するのも難しいので、GAE/Jに特化したフレームワークを利用するのが早道ではないでしょうか。

 ただcpu_msをこれだけ減らしても起動時間の改善は限定的でしたので、spin upに時間が掛かるのは現在のGAE/Jではどうしようもないのかもしれません(「Request was aborted」のエラーも少なくなったものの依然として発生しています)。