(注:相关代码请参考 com.ql.util.express.test.ExpressCacheTest类,
QLExpress源代码下载地址:http://code.taobao.org/p/QLExpress/src/ )
1、QLExpress的缓存带来的好处:
自带了一个本地缓存,用于缓存指令集,已减少编译阶段的时间消耗。
@Test
public void testScriptCache() throws Exception {
runner.addMacro("计算平均成绩", "(语文+数学+英语)/3.0");
IExpressContext<String, Object> context =new DefaultContext<String, Object>();
context.put("语文", 88);
context.put("数学", 99);
context.put("英语", 95);
long times =10000;
long start = new java.util.Date().getTime();
while(times-->0){
calulateTask(false, context);
}
long end = new java.util.Date().getTime();
echo("不做缓存耗时:"+ (end-start) +" ms");
times =10000;
start = new java.util.Date().getTime();
while(times-->0){
calulateTask(true, context);
}
end = new java.util.Date().getTime();
echo("做缓存耗时:"+ (end-start) +" ms");
}
private void echo(Object obj){
System.out.println(obj);
}
private void calulateTask(boolean isCache, IExpressContext<String, Object> context) throws Exception{
runner.execute("计算平均成绩", context, null, isCache, false);
}
实验结果:效果是非常明显的!
不做缓存耗时:890 ms
做缓存耗时:22 ms
2、ExpressRunner 自带的缓存
在同一个ExpressRunner执行器内是全局的,脚本间也可以相互调用,非常的强大。
适用场景:业务逻辑非常复杂,但是全局统一,业务逻辑需要很高的复用性。
@Test
public void testLocalCacheMutualImpact()throws Exception {
//缓存在本地的脚本都是全局的,可以相互调用
runner.addMacro("计算平均成绩", "(语文+数学+英语)/3.0");
runner.addMacro("是否优秀", "计算平均成绩>90");
IExpressContext<String, Object> context =new DefaultContext<String, Object>();
context.put("语文", 88);
context.put("数学", 99);
context.put("英语", 95);
echo(runner.execute("是否优秀", context, null, false, false));
}
3、独立于ExpressRunner的外部缓存处理器
适用场景:业务逻辑相对简单,脚本只依赖系统函数,不相互依赖,需要比较高的脚本隔离性和安全性,避免相互影响。
@Test
public void testRemoteCache(){
//数据的预先加载
ExpressRunner runner =new ExpressRunner();
ExpressRemoteCacheRunner cacheRunner = new LocalExpressCacheRunner(runner);
cacheRunner.loadCache("计算平均成绩", "(语文+数学+英语)/3.0");
cacheRunner.loadCache("是否优秀", "计算平均成绩>90");
IExpressContext<String, Object> context =new DefaultContext<String, Object>();
context.put("语文", 88);
context.put("数学", 99);
context.put("英语", 95);
//ExpressRemoteCacheRunner都只能执行自己原有的脚本内容,而且相互之间隔离,保证最高的脚本安全性
echo(cacheRunner.execute("计算平均成绩", context, null, false, false, null));
try{
echo(cacheRunner.execute("计算平均成绩>90", context, null, false, false, null));
}catch(Exception e){
echo("ExpressRemoteCacheRunner只支持预先加载的脚本内容");
}
try{
echo(cacheRunner.execute("是否优秀", context, null, false, false, null));
}catch(Exception e){
echo("ExpressRemoteCacheRunner不支持脚本间的相互调用");
}
}
总结下:
1、缓存主要是将 文本-》生成指令集 这个过程缓存起来,所以ExpressRunner的编译执行的,但是编译过程又属于表达式类型脚本,只要符合定义的语法规范即可。
2、ExpressRunner自带的缓存会全局保存,每一次脚本执行的时候可以依赖到以前的指令。
3、ExpressRemoteCacheRunner每一次load脚本的时候,只将本次编译好的指令集缓存起来,可以放在本地也可以放入远程的缓存系统中(如淘宝的 tair 等),所以牺牲了复用性,得到了安全性和独立性。