java scriptengine_java ScriptEngine

rorHandling(new

String[]{"-d","/home/guanbin","/home/guanbin/g.gv"}, true);

将g.gv编译为g.class

g.gv

PARAMS['name']='jack';将g.class反编译: javap -c -private -s g >

g.java

Compiled from "g.gv"public class g extends groovy.lang.Script{

public static transient boolean __$stMC; public static long

__timeStamp; public static long

__timeStamp__239_neverHappen1368583825046; public g(); public

g(groovy.lang.Binding); public static void

main(java.lang.String[]); public java.lang.Object run(); ........

public void super$3$println(java.lang.Object); public boolean

super$1$equals(java.lang.Object); public java.lang.Object

super$3$invokeMethod(java.lang.String, java.lang.Object); public

int super$1$hashCode(); static java.lang.Class

class$(java.lang.String);}

对于完成编译的class,会进行本地缓存,从而提高效率(key = script text, value = Class)

final ScriptEngineManager factory = new ScriptEngineManager();final

AtomicLong scriptCost = new AtomicLong();final long timeb =

System.currentTimeMillis();final AtomicLong count = new

AtomicLong();ExecutorService service =

Executors.newFixedThreadPool(11);for(int i = 0; i < 10; i)

service.execute(new Runnable() { @Override public void run() {

ScriptEngine engine = factory.getEngineByName("groovy"); // new

ScriptEngine obj, cache will expired while(true) { Map map = new

HashMap(); String prefix =

String.valueOf(System.nanoTime()).substring(5);//

engine.put("PARAMS_" prefix, map); // without cache

engine.put("PARAMS", map); // with cache for(int j = 0; j < 10;

j) {// String script =

String.format("PARAMS_%s['name_%s']='jack_%s';",prefix, prefix j,

prefix j); String script = "PARAMS['name']='jack';"; try {

count.incrementAndGet(); long b = System.nanoTime();

engine.eval_r(script); scriptCost.addAndGet(System.nanoTime()-b); }

catch (Exception e) { e.printStackTrace(); return; } } } }

});service.execute(new Runnable() { @Override public void run() {

while(true) { try { Thread.sleep(3000); } catch

(InterruptedException e) { e.printStackTrace(); } long costNano =

scriptCost.get(); long c = count.get(); long time =

System.currentTimeMillis()-timeb;

System.out.println(String.format("time:%s, count:%s, tps:%s,

average:%s", time, c, c*1000/time, costNano/c)); }

}});带cache:

time:6570503, count:82003860, tps:12480,

average:498863time:6573505, count:82040373, tps:12480,

average:498899cpu = 86%, load = 3.0

不带cache:

time:91847, count:5792, tps:63, average:156288377time:95113,

count:6058, tps:63, average:154671248time:98113, count:6238,

tps:63, average:155319788cpu = 97%, load = 2.5

clz cache map存在于GroovyScriptEngineImpl中(ManagedConcurrentMap

classMap)

而每次ScriptEngineFactory.getEngine("goovy")都会新构建一个GroovyScriptEngineImpl,于是cache失效,因此需要尽量重用ScriptEngine。

但是派克钢笔,ScriptEngine不是线程安全的。

AbstractScriptEngine -> SimpleScriptContext -> engineScope =

SimpleBindings -> map

通过scriptEngine.put(k,v)操作放入的数据,不可被多个线程同时访问

由于在web容器中,线程是复用的,应此将ScriptEngine作为ThreadLocal注入和获取,可以是一个解决方案。

GroovyScriptEngineImpl.eval_r(String script) { Class clz =

getFromMap(script); if(clz == null) clz =

GroovyClzLoader.parseClass(script); } Script obj =

clz.newInstance(); obj.setBinding(binding); obj.run();}

自定义GroovyClassLoader完成Class类的全局cache

public class CachedGroovyClassLoader extends GroovyClassLoader { //

script-string-to-generated Class map private static final Map();

private GroovyClassLoader proxyCL; public

CachedGroovyClassLoader(GroovyClassLoader proxyCL) { this.proxyCL =

proxyCL; } public Class

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值