我正在编写一个批处理excel文件的程序。将每行的数据放入映射中,文件名和工作表名称确定处理获取的数据的脚本。这些脚本没有捆绑到我的程序中,它们甚至不是实现特定接口的类。
这是处理循环逻辑:
excelfile.eachLineOnSheet { line, sheet ->
def data = extractData();
def lineprocessorscript = determineLineProcessor(excelfile, sheet);
Eval.xy data, outputfile, lineprocessorscript
}
当然这很容易,但在大文件上我想提高性能。首先我缓存了行处理器的代码,以便.groovy文件只读一次。
是否有可能通过以某种方式缓存编译的脚本来加快Eval.xy的速度? 我想保持我的脚本简单,以便不实现任何接口或东西。
答案 0 :(得分:3)
我对它的看法
deg gcl = ... // probably new GroovyClassLoader(this.class.classLoader)
def cache = [:].withDefault{gcl.parseClass(new File(it))}
...
lineprocessors.each {
cache[it].newInstance([someVariable:1, otherVariable:2] as Binding).run()
}
关于你自己答案的几条评论
你不需要自己创建gsc,只需用gcl加载文件。
如果你正在处理脚本,你真的不需要InvokerHelper
,你可以自己实例化它们
利用groovy syntax = D
答案 1 :(得分:1)
Eval.xy
调用GroovyShell.evaluate
方法。各种形式的GroovyShell.evaluate
都归结为这种形式:
public Object evaluate(GroovyCodeSource codeSource)
throws CompilationFailedException {
Script script = parse(codeSource);
script.setBinding(context);
return script.run();
}
我还没有尝试过,但您可以通过为XLS表中的每一行使用不同的绑定调用它来重用Script
对象。
答案 2 :(得分:1)
GroovyClassLoader
有一个内置缓存,但是从Eval
方向调用时,缓存已关闭:
private Class parseClass(final GroovyCodeSource codeSource) throws CompilationFailedException {
// Don't cache scripts
return loader.parseClass(codeSource, false);
}
为什么不缓存脚本..?这正是我需要的...... :-)所以我写了Eval根据来源做的东西,这就出来了:
lineprocessors.each {
if(cachedLineProcessorCodes[it] == null) {
def gsc = new GroovyCodeSource(new File(it).getText(), it, 'DEFAULT_CODE_BASE')
Class cc = gcl.parseClass(gsc, true)
cachedLineProcessorCodes[it] = cc
}
def binding = new Binding()
binding.setVariable("x", linedata)
binding.setVariable("y", lineProcFiles[it])
def Script sc = InvokerHelper.createScript(cachedLineProcessorCodes[it], binding)
sc.run()
//Eval.xy linedata, lineProcFiles[it], new File(it).getText()
}
在我的情况下,当groovy脚本处理7900行时,运行时间从~73s减少到~5s。
答案 3 :(得分:1)
您还可以通过测试http://mvel.codehaus.org/Performance+of+MVEL+2.0更快地将MVEL用于此类任务,而且不会更困难。
答案 4 :(得分:0)
你应该预先编写你的脚本,这通常是最激烈的部分:
String code = '$obj.toString()'
GroovyShell shell = new GroovyShell()
Script script = shell.parse(code, 'preparsed')
items.each {item ->
sh.setVariable('$obj', item)
Object result = s.run()
}