2

Java アプリケーション内で呼び出される groovy eval(string) メソッドに関するパフォーマンスの問題の原因を突き止めようとしています。次のコードを実行すると;

String pattern = "test = ['one','two','three']";
engine.eval(pattern)

ほとんど時間がかからない (0 ~ 1ms)

しかし、私が次のように言うなら

String first = "['one','two','three']";
String pattern = "test = " + first; // "identical" String to first approach 
engine.eval(pattern)

実行には約 30 ミリ秒以上かかります。

さらに悪いことに、数千回呼び出した後は 60 ~ 70 ミリ秒にもなりますが、2 つの実装間の時間差ほど気にする必要はありません。

なぜこれが起こっているのか、これを回避する方法についての提案はありますか? Java および/または Groovy コンパイラーと関係があると思われ、compile() メソッドを調べ始めましたが、既存のコードを機能させる簡単な方法があればそれを好みます (それを変更する必要が少ない)仕方)。

4

4 に答える 4

1

https://github.com/groovy/groovy-core/blob/master/subprojects/groovy-jsr223/src/main/java/org/codehaus/groovy/jsr223/GroovyScriptEngineImpl.java?source=ccを見ると、文字列をクラスにマッピングするためのキャッシュが見つかります。問題は、ManagedConcurrentMap が基本的に ID ハッシュマップであることです。つまり、同じ文字列を何度も使用すると、後続の実行でコンパイルがスキップされるため、高速になります。問題のあるバージョンは毎回新しい文字列を作成するため、毎回コンパイルする必要があり、毎回新しいクラスも生成されます。

これを回避する方法: ハッシュ ベースのキャッシュを作成する

于 2013-10-09T14:39:49.247 に答える
0

最終的に私たちはそれを認識しました

eval("['one','two','three']")

正確にそれを返すので、

Object test = engine.eval(first)

と同等です

engine.eval("test = " + "['one','two','three']") // see text above for exact syntax
Object test = engine.get("test")

それでも、実際にはまったく時間がかかりません。

なぜパターンを動的にすることが eval() のパフォーマンスに劇的な影響を与えるのか、私はまだ非常に興味がありますが、Java および/またはグルーヴィーなランタイム要素を深く理解している人がそれに光を当てる必要があると思います.

助けようとしたすべての人に感謝します。よろしく、

ps。

于 2013-10-07T15:37:41.673 に答える
0

呼び出しの時間をどのように測定していますか? 可能であれば、各部分 (文字列の構築と eval()) を測定して、時間がかかっている部分と、反復回数が増えるにつれて増加する部分を判断します。反復回数が増えると時間が増えるとのことなので、ガベージコレクションを見てください。最初のケースでは単一の String を使用します。後者のケースでは、反復ごとに新しい String を構築しているため、メモリを消費しています。ヒープ制限に達している可能性があります。

これを確認するための非常に便利なツールの 1 つが VisualVM です。http://visualvm.java.net/

于 2013-10-04T22:00:06.610 に答える
0

evalはどの言語でも遅いことで有名であり、しばしば近づかないように勧められます (「eval は悪です」)。ただし、コードでは、評価自体ではなく、文字列の連結が速度低下を引き起こしているようです。

それでも、数ミリ秒は心配する必要はありません。これがコードでパフォーマンスのボトルネックを引き起こしていると判断しましたか? コードを細かく管理すると、将来的にバグや不明確なコードが発生する可能性があり、さらに悪い影響を与える可能性があります。

于 2013-10-04T17:41:01.993 に答える