我试图通过在 Java 应用程序中调用 groovy eval(string) 方法来追踪性能问题的根源。如果我执行下面的代码;
String pattern = "test = ['one','two','three']";
engine.eval(pattern)
它几乎可以立即运行(0 到 1 毫秒)
但是,如果我说下面的话
String first = "['one','two','three']";
String pattern = "test = " + first; // "identical" String to first approach
engine.eval(pattern)
运行大约需要 30 多毫秒。
更糟糕的是,在数千次调用之后,它会高达 60 - 70 毫秒,尽管我对这两个实现之间的时间差远没有那么担心。
关于为什么会发生这种情况的任何解释/关于如何避免这种情况的建议?我怀疑它与 Java 和/或 Groovy 编译器有关,并且我已经开始研究 compile() 方法,但如果有一种简单的方法可以使现有代码正常工作,我会更喜欢它(需要更改的东西更少)方式)。
最佳答案
如果你看https://github.com/groovy/groovy-core/blob/master/subprojects/groovy-jsr223/src/main/java/org/codehaus/groovy/jsr223/GroovyScriptEngineImpl.java?source=cc你会发现一个用于将字符串映射到类的缓存。问题是 ManagedConcurrentMap 基本上是一个身份 HashMap ,这意味着如果您一遍又一遍地使用相同的字符串,它会很快,因为后续运行会跳过编译。问题版本每次都创建一个新的字符串,因此每次都需要编译,导致每次都生成一个新的类。
关于如何避免这种情况:创建基于哈希的缓存
关于java - groovy 脚本 eval(string) 方法的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19187349/