作者:聂勇 欢迎转载,请保留作者信息并说明文章来源!
JDK6增加了一个重要的特性,实现JSR 223规范支持脚本语言,使得Java可以通过脚本引擎执行JavaScript,Python等脚本语言代码。JDK6包含了一个基于Mozilla Rhino的 脚本语言引擎,支持JavaScript。其他的脚本语言可以按JSR 223规范实现脚本引擎,JDK中有一个ScriptEngineManager类,它可以通过jar服务发现(Service Discovery)机制寻找合适的脚本引擎类(ScriptEngine)。
脚本语言给人第一印象,它是逐行解释执行的,但JSR 223规范定义了脚本两种不同的运行方式:
是否支持编译功能,由具体的脚本引擎决定。JDK6自带的JavaScript引擎同时支持解释运行和编译运行两种方式,下面就对比这两种方式下脚本运行的性能。
代码
完整的源代码
1、解释运行。关键代码如下:
1 2 3 4 5 6 7 8 9 10
| public void parse(String script, Map<String, Object> vars) throws ScriptException { ScriptEngine scriptEngine = getScriptEngine("javascript"); long startTime = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { Bindings binds = createBinding(vars, scriptEngine); scriptEngine.eval(script, binds); } long usedTime = System.currentTimeMillis() - startTime; System.out.println( String.format("每次都解释脚本执行%d次消耗%d毫秒", COUNT, usedTime) ); }
|
2、先编译,再运行。关键代码如下:
1 2 3 4 5 6 7 8 9 10 11 12
| public void compile(String script, Map<String, Object> vars) throws ScriptException { ScriptEngine scriptEngine = getScriptEngine("javascript"); Compilable compileEngine = (Compilable) scriptEngine; CompiledScript compileScript = compileEngine.compile(script); long startTime = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { Bindings binds = createBinding(vars, scriptEngine); compileScript.eval(binds); } long usedTime = System.currentTimeMillis() - startTime; System.out.println( String.format("编译脚本后执行%d次消耗%d毫秒", COUNT, usedTime) ); }
|
性能对比
测试环境,运行在VirtualBox中的虚拟机:
操作系统:Redhat 5.7 64bit
CPU:Intel(R) Core(TM) i3 CPU M380@2.53GHz * 2
内存:2.5GB
跑了四次测试,结果如下:
|
运行次数 |
解释运行(单位:毫秒) |
先编译再运行(单位:毫秒) |
第一次 |
100000 |
16898 |
15129 |
第二次 |
100000 |
15704 |
14291 |
第三次 |
100000 |
17724 |
14938 |
第四次 |
100000 |
16987 |
14828 |
注:在高并发的场景中,两种方式的性能差距比上述结果要更大。