作者:宋云
使用ABCL的效率问题
最初使用ABCL在LISP中调用JAVA类是总是找不到类,查阅ABCL的样例README总算找到一个靠谱的方法:
javac -cp
abcl.jar Main.java
java -cp abcl.jar;. Main
需要注意java文件的package,一定要对应,否则同样找不到.class。按照ABCL的样例做如下实验,下面是Main.lisp中定义的函数:
(defun void-function
(param)
(let* ((class (jclass
"Main"))
(intclass
(jclass "int"))
(method (jmethod class
"addTwoNumbers" intclass intclass))
(result (jcall method
param 2 5)))
(format
t "in void-function, result of calling addTwoNumbers(2, 5): ~a~%"
result)))
该函数执行类Main的方法addTwoNumbers,下面是Main.java:
import org.armedbear.lisp.Fixnum;
import org.armedbear.lisp.Function;
import org.armedbear.lisp.Interpreter;
import org.armedbear.lisp.JavaObject;
import org.armedbear.lisp.LispObject;
import org.armedbear.lisp.Packages;
import org.armedbear.lisp.Symbol;
public class Main{
public
static void main(String[] argv){
try{
long
btime = System.currentTimeMillis();
Main
thisObject= new Main();
System.out.println("Main:"+(System.currentTimeMillis()-btime));
Interpreter
interpreter= Interpreter.createInstance();
System.out.println("Interpreter:"+(System.currentTimeMillis()-btime));
interpreter.eval_r("(load
\"Main.lisp\")");
System.out.println("Load:"+(System.currentTimeMillis()-btime));
// the function is not in a separate package, thus
the43
//
correct package is CL-USER. Symbol names are44
//
upper case. Package needs the prefix, because
java45
//
also has a class named Package.46
org.armedbear.lisp.Package
defaultPackage=
Packages.findPackage("CL-USER");
System.out.println("DefPackage:"+(System.currentTimeMillis()-btime));
Symbol
voidsym= defaultPackage.findAccessibleSymbol("VOID-FUNCTION");
System.out.println("Find
Symbol:"+(System.currentTimeMillis()-btime));
Function
voidFunction= (Function)
voidsym.getSymbolFunction();
System.out.println("voidFunction:"+(System.currentTimeMillis()-btime));
LispObject
lo = voidFunction.execute(new
JavaObject(thisObject));
System.out.println("execute:"+(System.currentTimeMillis()-btime));
System.out.println(lo.toString());
}catch
(Throwable t){
System.out.println("exception!");
t.printStackTrace();
}
}
public
int addTwoNumbers(int a, int b)
{
return a+ b;
}
}
该类执行Main.lisp,在Main.lisp中调用自身的addTwoNumbers,同时输出每一步距离程序刚开始运行时所消耗的时间(单位毫秒),运行结果:
Main:0
Interpreter:12313
Load:12360
DefPackage:12360
Find
Symbol:12360
voidFunction:12360
in void-function, result
of calling addTwoNumbers(2, 5): 7
execute:31641
COMMON-LISP:NIL
很明显,创建Interpreter很耗时间12313毫秒,而反调用java中的函数更好时间(31641-12360=19281毫秒),耗时非常吓人,恐怕用来做WebServer很值得考虑。
但是考虑到这个函数的执行过程很复杂,调用了lisp又返回来调用Java。下面更改一下只调用纯lisp函数:
(defun add (a b
c)
(+
a b c))
Symbol
voidsym= defaultPackage.findAccessibleSymbol("ADD");
LispObject lo =
voidFunction.execute(Fixnum.getInstance(1),
Fixnum.getInstance(2),
Fixnum.getInstance(3));
计算结果如下:
Main:0
Interpreter:13141
Load:13172
DefPackage:13172
Find
Symbol:13172
voidFunction:13172
execute:13172
org.armedbear.lisp.Fixnum@6
这表明纯粹的调用LISP函数并不消耗多少时间,基本就等于LISP函数的执行时间。因此可以考虑在JAVA中调用纯LISP函数。
ABCL资料如此只少,真心需要多花点时间琢磨了!
JAVA中调用LISP函数
下面介绍在JAVA中调用LISP的过程。首先要获取一个解析器实例:
Interpreter
interpreter= Interpreter.createInstance();
通过解析器载入lisp文件:
interpreter.eval_r("(load
\"Main.lisp\")");
获取包:
org.armedbear.lisp.Package
defaultPackage=
Packages.findPackage("CL-USER");
寻找函数标示:
Symbol
voidsym=
defaultPackage.findAccessibleSymbol("VOID-FUNCTION");
获取函数实例:
Function
voidFunction= (Function)
voidsym.getSymbolFunction();
执行函数:
LispObject lo =
voidFunction.execute(
new
JavaObject(thisObject));
至于如何设置函数输入参数的类型还有待研究。
转发至微博
转发至微博