mirror of
https://github.com/Estom/notes.git
synced 2026-02-04 02:53:57 +08:00
251 lines
8.9 KiB
Java
251 lines
8.9 KiB
Java
package cn.aofeng.demo.script;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.HashMap;
|
||
import java.util.Iterator;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
|
||
import javax.script.Bindings;
|
||
import javax.script.Compilable;
|
||
import javax.script.CompiledScript;
|
||
import javax.script.ScriptEngine;
|
||
import javax.script.ScriptEngineManager;
|
||
import javax.script.ScriptException;
|
||
|
||
/**
|
||
* 多个脚本引擎执行JavaScript的性能比较。
|
||
*
|
||
* @author <a href="mailto:aofengblog@163.com">聂勇</a>
|
||
*/
|
||
public class MultiScriptEngineCompare {
|
||
|
||
public final static String PARSE = "parse";
|
||
public final static String COMPILE = "compile";
|
||
|
||
/**
|
||
* 获取指定的脚本引擎执行指定的脚本(解释执行)。
|
||
*
|
||
* @param scriptEngineName 脚本引擎名称
|
||
* @param script 脚本
|
||
* @param count 脚本的执行次数
|
||
* @param vars 绑定到脚本的变量集合
|
||
* @throws ScriptException 执行脚本出错
|
||
*/
|
||
public ExecuteResult parse(String scriptEngineName, String script, int count,
|
||
Map<String, Object> vars) throws ScriptException {
|
||
ScriptEngine scriptEngine = getScriptEngine(scriptEngineName);
|
||
long startTime = System.currentTimeMillis();
|
||
for (int i = 0; i < count; i++) {
|
||
runSingleScript(script, vars, scriptEngine);
|
||
}
|
||
long usedTime = System.currentTimeMillis() - startTime;
|
||
|
||
ExecuteResult result = new ExecuteResult();
|
||
result.setEngine(scriptEngine.getFactory().getEngineName());
|
||
result.setScript(script);
|
||
result.setBindParam(vars.toString());
|
||
result.setExecuteCount(count);
|
||
result.setExecuteType(PARSE);
|
||
result.setUsedTime(usedTime);
|
||
|
||
return result;
|
||
}
|
||
|
||
private void runSingleScript(String script, Map<String, Object> vars,
|
||
ScriptEngine scriptEngine) throws ScriptException {
|
||
if (null == vars || vars.isEmpty()) {
|
||
scriptEngine.eval(script);
|
||
} else {
|
||
Bindings binds = createBinding(scriptEngine, vars);
|
||
scriptEngine.eval(script, binds);
|
||
}
|
||
}
|
||
|
||
public ExecuteResult compile(String scriptEngineName, String script, int count,
|
||
Map<String, Object> vars) throws ScriptException {
|
||
ScriptEngine scriptEngine = getScriptEngine(scriptEngineName);
|
||
Compilable compileEngine = (Compilable) scriptEngine;
|
||
CompiledScript compileScript = compileEngine.compile(script);
|
||
long startTime = System.currentTimeMillis();
|
||
for (int i = 0; i < count; i++) {
|
||
runSingleScript(compileScript, vars, scriptEngine);
|
||
}
|
||
long usedTime = System.currentTimeMillis() - startTime;
|
||
|
||
ExecuteResult result = new ExecuteResult();
|
||
result.setEngine(scriptEngine.getFactory().getEngineName());
|
||
result.setScript(script);
|
||
result.setBindParam(vars.toString());
|
||
result.setExecuteCount(count);
|
||
result.setExecuteType(COMPILE);
|
||
result.setUsedTime(usedTime);
|
||
|
||
return result;
|
||
}
|
||
|
||
private void runSingleScript(CompiledScript compileScript, Map<String, Object> vars,
|
||
ScriptEngine scriptEngine) throws ScriptException {
|
||
if (null == vars || vars.isEmpty()) {
|
||
compileScript.eval();
|
||
} else {
|
||
Bindings binds = createBinding(scriptEngine, vars);
|
||
compileScript.eval(binds);
|
||
}
|
||
}
|
||
|
||
protected void log(String msg) {
|
||
System.out.println(msg);
|
||
}
|
||
|
||
protected void log(String msg, Object... args) {
|
||
log( String.format(msg, args) );
|
||
}
|
||
|
||
/**
|
||
* 根据名称获取脚本引擎。
|
||
*
|
||
* @param name 脚本引擎名称
|
||
* @return 实现了{@link ScriptEngine}的脚本引擎。如果没有对应的脚本引擎,返回null。
|
||
*/
|
||
public ScriptEngine getScriptEngine(String name) {
|
||
ScriptEngineManager sem = new ScriptEngineManager();
|
||
return sem.getEngineByName(name);
|
||
}
|
||
|
||
private Bindings createBinding(ScriptEngine scriptEngine, Map<String, Object> vars) {
|
||
Bindings binds = scriptEngine.createBindings();
|
||
if (null != vars && !vars.isEmpty()) {
|
||
binds.putAll(vars);
|
||
}
|
||
|
||
return binds;
|
||
}
|
||
|
||
/**
|
||
* @param args 执行次数
|
||
* @throws ScriptException
|
||
*/
|
||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||
public static void main(String[] args) throws ScriptException {
|
||
if ( args.length != 2) {
|
||
System.err.println("参数错误。\n语法格式:\n java cn.aofeng.demo.script.MultiScriptEngineCompare 脚本执行次数 脚本执行方式(parse|compile)\n使用示例:\n java cn.aofeng.demo.script.MultiScriptEngineCompare 100000 parse");
|
||
System.exit(-1);
|
||
}
|
||
int count = Integer.parseInt(args[0]);
|
||
String executeType = args[1];
|
||
|
||
String[] scriptEngineList = {"JavaScript", "JEXL"};
|
||
|
||
String script1 = "var c = a + b;" +
|
||
"var d = a * b;" +
|
||
"var e = a / b;" +
|
||
"var f = a % b;" +
|
||
"var g = a - b;" +
|
||
"var result = ((a * 5) > b || b * 10 >= 100) && (a * b > 99);";
|
||
Map<String, Object> vars1 = new HashMap<String, Object>(2);
|
||
vars1.put("a", 20);
|
||
vars1.put("b", 9);
|
||
|
||
String script2 = "var result = src.indexOf(b);";
|
||
Map<String, Object> vars2 = new HashMap<String, Object>(2);
|
||
vars2.put("src", "compare performance javascript and jexl");
|
||
vars2.put("b", "script");
|
||
|
||
String[] scriptList = {script1, script2};
|
||
Map[] varsList = {vars1, vars2};
|
||
|
||
MultiScriptEngineCompare msec = new MultiScriptEngineCompare();
|
||
List<MultiScriptEngineCompare.ExecuteResult> resultList = new ArrayList<MultiScriptEngineCompare.ExecuteResult>();
|
||
for (int i = 0; i < scriptEngineList.length; i++) {
|
||
for (int j = 0; j < scriptList.length; j++) {
|
||
if (PARSE.equalsIgnoreCase(executeType)) {
|
||
resultList.add( msec.parse(scriptEngineList[i], scriptList[j], count, varsList[j]) );
|
||
} else if (COMPILE.equalsIgnoreCase(executeType)) {
|
||
resultList.add( msec.compile(scriptEngineList[i], scriptList[j], count, varsList[j]) );
|
||
} else {
|
||
msec.log("错误的执行方式:%s", executeType);
|
||
}
|
||
}
|
||
}
|
||
|
||
List<String[]> arrayList = new ArrayList<String[]>();
|
||
arrayList.add(new String[]{"脚本引擎", "脚本", "脚本绑定参数", "脚本执行次数", "脚本执行类型", "消耗时间(毫秒)", "JDK版本"});
|
||
for (Iterator iterator = resultList.iterator(); iterator.hasNext();) {
|
||
ExecuteResult er = (ExecuteResult) iterator.next();
|
||
arrayList.add(new String[]{er.getEngine(),
|
||
er.getScript(),
|
||
er.getBindParam(),
|
||
String.valueOf(er.getExecuteCount()),
|
||
er.getExecuteType(),
|
||
String.valueOf(er.getUsedTime()),
|
||
er.getJdkVersion()});
|
||
}
|
||
|
||
String[][] table = new String[arrayList.size()][7];
|
||
arrayList.toArray(table);
|
||
|
||
PrettyTable prettyTable = new PrettyTable(System.out);
|
||
prettyTable.print(table);
|
||
}
|
||
|
||
static class ExecuteResult {
|
||
|
||
private String engine;
|
||
private String script;
|
||
private String bindParam;
|
||
private int executeCount;
|
||
private String executeType;
|
||
private long usedTime;
|
||
private String jdkVersion;
|
||
|
||
public ExecuteResult() {
|
||
this.jdkVersion = System.getProperty("java.version");
|
||
}
|
||
|
||
public String getEngine() {
|
||
return engine;
|
||
}
|
||
public void setEngine(String engine) {
|
||
this.engine = engine;
|
||
}
|
||
public String getScript() {
|
||
return script;
|
||
}
|
||
public void setScript(String script) {
|
||
this.script = script;
|
||
}
|
||
public String getBindParam() {
|
||
return bindParam;
|
||
}
|
||
public void setBindParam(String bindParam) {
|
||
this.bindParam = bindParam;
|
||
}
|
||
public int getExecuteCount() {
|
||
return executeCount;
|
||
}
|
||
public void setExecuteCount(int executeCount) {
|
||
this.executeCount = executeCount;
|
||
}
|
||
public String getExecuteType() {
|
||
return executeType;
|
||
}
|
||
public void setExecuteType(String executeType) {
|
||
this.executeType = executeType;
|
||
}
|
||
public long getUsedTime() {
|
||
return usedTime;
|
||
}
|
||
public void setUsedTime(long usedTime) {
|
||
this.usedTime = usedTime;
|
||
}
|
||
public String getJdkVersion() {
|
||
return jdkVersion;
|
||
}
|
||
public void setJdkVersion(String jdkVersion) {
|
||
this.jdkVersion = jdkVersion;
|
||
}
|
||
}
|
||
|
||
}
|