初回アクセス時だけ .groovy をコンパイルして実行、2回目以降はコンパイル済みクラスを実行、なんて、できないですかね?

211 views
Skip to first unread message

nabedge

unread,
Feb 19, 2014, 5:39:46 AM2/19/14
to jg...@googlegroups.com
JGGUGの皆さん、こんばんは。
渡辺と申します。

私は http://mixer2.org/ という、javaアプリ用のテンプレートエンジンをossとして作っております。
Webデザイナーさんに作ってもらったhtml/cssを、
jspのカスタムタグまみれに書き換える手間を無くしてしまおうというものです。

で、さらに一歩踏み込んで、画面処理部分をjavaで書くのではなく
groovyで書けるようにできれば、
見栄えにこだわるエンドユーザーやWebデザイナでも
プログラミングしやすくなるんじゃないかと思いまして、
こんなサンプルアプリを作りました。

https://github.com/nabedge/mixer2-groovy/

まだたたき台レベルなんですが、src/main/resources/index.groovy をいじれば、
画面の表示内容を変えることができます。

ここで問題なのが性能です。
jmeterで軽く負荷をかけてみたところ、やはり通常のjavaプログラミングよりも
5倍から10倍は遅いようです。
ちなみにjavaからgroovyを呼び出している箇所はここです。
https://github.com/nabedge/mixer2-groovy/blob/master/src/main/java/org/mixer2/sample/view/IndexView.java

GroovyShellを使っている限りは性能が出なくて当然だとは思います。
そこで、スレッドの件名のとおりなんですが、
 1)初回アクセス時だけ .groovy をコンパイルして実行
 2)2回目以降はコンパイル済みクラスを実行
といったことをする、うまい方法って、ないものでしょうか?

--------
http://mixer2.org/
http://nabedge.blogspot.jp/
http://www.slideshare.net/nabedge

今田 昇

unread,
Feb 19, 2014, 8:49:18 PM2/19/14
to jg...@googlegroups.com

渡辺さん

こんにちは。

 

今田と申します。

 

Groovyでいろいろ作るのは楽しいですよね。

 

一度parseしたScriptインスタンスをキャッシュしておく。

 

そのために、Singletonなファクトリクラスを作って、

.groovyソースのparseとキャッシュの機能を担ってもらう。

 

キャッシュのクリアをどうするか?とか、

.groovyソースのタイムスタンプをチェックするかしないか?

とか、

いろいろ考えればきりがないですが、

 

まずは、

スレッドセーフを考えて、

java.util.concurrent.ConcurrentHashMap

Scriptインスタンスをキャッシュするところからはじめてはいかがでしょうか?

--
このメールは Google グループのグループ「JGGUG」の登録者に送られています。
このグループから退会し、メールの受信を停止するには、jggug+un...@googlegroups.com にメールを送信します。
このグループに投稿するには、jg...@googlegroups.com にメールを送信してください。
http://groups.google.com/group/jggug
からこのグループにアクセスしてください。
その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。

UEHARA Junji

unread,
Feb 20, 2014, 12:08:32 AM2/20/14
to JGGUG
上原と申します。
Groovyではgroovy.util.GroovyScritptEngineが、
スクリプトソース修正時の更新検出・自動リロード機能
を持っておるようです。


を参考に、

--
// test.groovy
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

String[] roots = ["~/" ] as String[]
GroovyScriptEngine gse = new GroovyScriptEngine(roots);
Binding binding = new Binding();
binding.setVariable("input", "world");
while (true) {
    gse.run("hello.groovy", binding);
    println binding.getVariable("output")
    Thread.sleep(1000)
}
--

--
//  ~/hello.groovy
output = "Hello, ${input}++"
--

などを試したところ、hello.groovyの更新時にリロードされ
るようです。キャッシュとかがされているかは、
ドキュメント


から見るとされている印象がありますが、実際に確認できてはいません。
なお、コンパイルはオンメモリで行なわれます。

あと、スループットとしての実行性能が真に問題なら、
@CompileStaticとかも試してみると良いかもです。
いかがでしょう。


2014年2月19日 19:39 nabedge <nab...@gmail.com>:

--
このメールは Google グループのグループ「JGGUG」の登録者に送られています。
このグループから退会し、メールの受信を停止するには、jggug+un...@googlegroups.com にメールを送信します。
このグループに投稿するには、jg...@googlegroups.com にメールを送信してください。
http://groups.google.com/group/jggug からこのグループにアクセスしてください。
その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。



--
UEHARA Junji

nabedge

unread,
Feb 26, 2014, 10:47:45 PM2/26/14
to jg...@googlegroups.com
渡辺です。間があいてしまってすいません。

>一度parseしたScriptインスタンスをキャッシュしておく。

なるほど!と思って、groovyスクリプトをparseした状態の
scriptインスタンスをつかいまわすようにしてみたら、
通常のjavaコーディングとほぼ同じ性能がでました!ありがとうございます。

該当のコードはこれです。
https://github.com/nabedge/mixer2-groovy/blob/useParsedScript/src/main/java/org/mixer2/sample/view/IndexView.java

# スクリプトを実行するメソッドでsynchronizedをいれてあるのでスレッドセーフ性は崩れてないと思うんだけど

ただこれだと、今度は、Webデザイナーが逐一スクリプトを変更して画面出力を確認できるようにする、
という要件の実現が難しくなるかもしれませんので、トレードオフかなー。。
今田さんのおっしゃるようにもうすこし作り込んでみるかなー。

ありがとうございました。

2014年2月20日木曜日 10時49分18秒 UTC+9 Noboru:

このグループから退会し、メールの受信を停止するには、jggug+unsu...@googlegroups.com にメールを送信します。

Reply all
Reply to author
Forward
0 new messages