gpt4 book ai didi

javascript - Rhino 性能和编译脚本

转载 作者:行者123 更新时间:2023-11-29 15:38:35 24 4
gpt4 key购买 nike

我遇到了一些性能问题,因为在 Rhino 中执行 Javascript 代码很慢。

我编写了以下测试以查看性能如何随着不同的脚本执行方式而变化:

public class SimpleScriptsPerformanceTest {
private static int TIMES = 10000;

// no caching scope; without optimizations
@Test
public void testRhino1() {
Context ctx = Context.enter();
try {
ctx.setLanguageVersion(170);
ScriptableObject scriptScope = ctx.initStandardObjects();

long startTime = System.currentTimeMillis();
for (int i = 0; i < TIMES; i++) {
ctx.evaluateString(scriptScope, getScript1(), "script.js", 1, null);
}
long endTime = System.currentTimeMillis();
System.out.println("Total execution time (rhino1): " + (endTime-startTime) + "ms");

} catch (Exception e) {
e.printStackTrace();
} finally {
Context.exit();
}
}

// no caching scope; with optimizations
@Test
public void testRhino2() {
Context ctx = Context.enter();
try {
ctx.setOptimizationLevel(9);
ctx.setLanguageVersion(170);
ScriptableObject scriptScope = ctx.initStandardObjects();

long startTime = System.currentTimeMillis();
for (int i = 0; i < TIMES; i++) {
ctx.evaluateString(scriptScope, getScript1(), "script.js", 1, null);
}
long endTime = System.currentTimeMillis();
System.out.println("Total execution time (rhino2): " + (endTime-startTime) + "ms");

} catch (Exception e) {
e.printStackTrace();
} finally {
Context.exit();
}
}

// caching scope; with optimizations for main function and for calling code
@Test
public void testRhino3() {
Context ctx = Context.enter();
try {
ctx.setOptimizationLevel(9);
ctx.setLanguageVersion(170);
ScriptableObject scriptScope = ctx.initStandardObjects();
ctx.evaluateString(scriptScope, getScript1(), "script.js", 1, null);
ctx.setOptimizationLevel(9);

long startTime = System.currentTimeMillis();
for (int i = 0; i < TIMES; i++) {
ctx.evaluateString(scriptScope, getScript2(), "script.js", 1, null);
}
long endTime = System.currentTimeMillis();
System.out.println("Total execution time (rhino3): " + (endTime-startTime) + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
Context.exit();
}
}

// caching scope; with optimizations for main function; no optimizations for calling code
@Test
public void testRhino4() {
Context ctx = Context.enter();
try {
ctx.setOptimizationLevel(9);
ctx.setLanguageVersion(170);
ScriptableObject scriptScope = ctx.initStandardObjects();
ctx.evaluateString(scriptScope, getScript1(), "script.js", 1, null);
ctx.setOptimizationLevel(-1);

long startTime = System.currentTimeMillis();
for (int i = 0; i < TIMES; i++) {
ctx.evaluateString(scriptScope, getScript2(), "script.js", 1, null);
}
long endTime = System.currentTimeMillis();
System.out.println("Total execution time (rhino4): " + (endTime-startTime) + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
Context.exit();
}
}
// caching scope; without optimizations; different contexts
@Test
public void testRhino5() {
ScriptableObject scriptScope = null;
Context ctx = Context.enter();
try {
ctx.setOptimizationLevel(9);
ctx.setLanguageVersion(170);
scriptScope = ctx.initStandardObjects();
ctx.evaluateString(scriptScope, getScript1(), "script.js", 1, null);
} catch (Exception e) {
e.printStackTrace();
} finally {
Context.exit();
}

ctx = Context.enter();
try {
ctx.setOptimizationLevel(-1);
ctx.setLanguageVersion(170);

long startTime = System.currentTimeMillis();
for (int i = 0; i < TIMES; i++) {
ctx.evaluateString(scriptScope, getScript2(), "script.js", 1, null);
}
long endTime = System.currentTimeMillis();
System.out.println("Total execution time (rhino5): " + (endTime-startTime) + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
Context.exit();
}
}

// script engine; eval
@Test
public void testScriptEngine1() throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");

long startTime = System.currentTimeMillis();
for (int i = 0; i < TIMES; i++) {
engine.eval(getScript1());
}
long endTime = System.currentTimeMillis();
System.out.println("Total execution time (scriptEngine1): " + (endTime-startTime) + "ms");
}

// script engine; compiled script
@Test
public void testScriptEngine2() throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Compilable compilingEngine = (Compilable)engine;
CompiledScript script = compilingEngine.compile(getScript1());

long startTime = System.currentTimeMillis();
for (int i = 0; i < TIMES; i++) {
script.eval();
}
long endTime = System.currentTimeMillis();
System.out.println("Total execution time (scriptEngine2): " + (endTime-startTime) + "ms");
}

private String getScript1() {
StringBuilder sb = new StringBuilder();
sb.append("var foo = function() {").append("\n");
sb.append(" var a = 5;").append("\n");
sb.append(" var b = 'test';").append("\n");
sb.append(" var c = 93.2;").append("\n");
sb.append(" var d = [];").append("\n");
sb.append(" for (var i = 0; i < 5; i++) {").append("\n");
sb.append(" if (i == 2) d.push('pepe');").append("\n");
sb.append(" else d.push('juan');").append("\n");
sb.append(" }").append("\n");
sb.append(" return res = a + b + c + d.join(',');").append("\n");
sb.append("}").append("\n");
sb.append("foo();").append("\n");
return sb.toString();
}

private String getScript2() {
StringBuilder sb = new StringBuilder();
sb.append("foo();").append("\n");
return sb.toString();
}
}

多次运行脚本后,我得到以下平均次数:

Total execution time (rhino1):        8120 ms
Total execution time (rhino2): 7946 ms
Total execution time (rhino3): 4350 ms
Total execution time (rhino4): 257 ms
Total execution time (rhino5): 188 ms
Total execution time (scriptEngine1): 1547 ms
Total execution time (scriptEngine2): 1090 ms

所以 rhino5 似乎是上述方法中最有效的,其中将函数“foo”放入范围内一次,然后在不同的上下文中,我在相同范围内调用该函数,根本没有优化。

根据这些结果,这些是我得到的结论:

  • 库和实用程序方法应在所有优化范围内运行。
  • 缓存作用域,这样您就不需要再次解析脚本。
  • 当您运行一次性脚本时,不要使用优化。
  • 不要使用 ScriptEngine 界面,因为它似乎比使用 Rhino 慢,即使在使用编译脚本时也是如此。

所以我的问题是:有没有一种方法可以更有效地运行 Rhino 脚本?

我有不会经常更改的脚本(但确实会更改并且需要在不停止应用程序的情况下更新它们),因此我可以编译它们并重新使用它们。但是我不确定我在做什么(缓存和重用范围)是最有效的方法。我看到有人建议将 Javascript 编译为 Java 字节码,但不确定如何做到这一点。

注意事项:

最佳答案

Rhino 引擎实现了 Compilable 接口(interface)。我认为这比必须一直评估脚本字符串要快。

Compilable compilingEngine = (Compilable) cEngine; 
CompiledScript compiledScript = compilingEngine.compile(script);

关于javascript - Rhino 性能和编译脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23975010/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com