Groovy 学习笔记3 运行效率

第一篇笔记里面,我说groovy运行的居然还满快的,其实是个误会了。我上次做八皇后还是在8080上面用basic做的,和现在奔四上面的groovy相比是没有意义的。特地又做了个对比试验:

 

 1 int  q = 9
 2 int [] i = new   int [q]
 3 int  count = 0
 4 long  t  =  System.currentTimeMillis();
 5 scan( 0 )
 6 println( " totle results: " + count)
 7 println( " totle time: " + (System.currentTimeMillis() - t));
 8 def scan(n) {
 9    if (n==q){
10        println(i.toList())
11        count++
12        return
13    }

14    i[n]=0
15    while(i[n]<q){
16        i[n] = i[n]+1
17        if (check(n))
18            scan(n+1)
19    }

20}

21 def check(n) {
22    if (n>0)
23        for (j in 0..<n) 
24            if (i[j]==i[n] || i[j]-i[n]==j-|| i[j]-i[n]==n-j )
25                return false
26    return true
27}


运行结果是:totle time:7271 (为了用groovy控制台运行的,直接用groovy命令运行还要慢一点)

java呢?

queens.java:

 

 1 public   class  queens  {
 2    static int q=9;
 3    static int[] i=new int[q];
 4    static int count=0;
 5    public static void main(String[] args){
 6        long t = System.currentTimeMillis();
 7        scan(0);
 8        System.out.println("totle results:"+count);
 9        System.out.println("totle time:"+(System.currentTimeMillis()-t));
10    }

11    private static void scan(int n){
12        if (n==q){
13            for (int k=0;k<q;k++) System.out.print(i[k]+(k==q-1?"/n":","));
14            count++;
15            return;
16        }

17        i[n]=0;
18        while(i[n]<q){
19            i[n] = i[n]+1;
20            if (check(n)){
21                scan(n+1);
22            }

23        }

24    }

25    private static boolean check(int n){
26        for(int j=0;j<n;j++){
27            if (i[j]==i[n] || i[j]-i[n]==j-|| i[j]-i[n]==n-j ){
28                return false;
29            }

30        }

31        return true;
32    }

33}

34

运行结果是:totle time:271




每次运行花费的时间略有不同,groovy和java的运行速度看来大致相差10~30倍左右。


能说这是脚本语言天生的缺陷吗?我们来看看同样是类似java语法的脚本语言javascript在IE里面的速度:

 1 var q = 9  
 2 var i = [] 
 3 var count = 0  
 4 var d  =   new  Date(); 
 5 scan( 0
 6 document.write( " totle results: " + count + " <br> "
 7 document.write( " time used: " + ( new  Date() - d) + " <br> "
 8
 9 function scan(n)
10    if (n==q)
11        document.write(i+"<br>"
12        count++ 
13        return 
14    }
 
15    i[n]=0 
16    while(i[n]<q){
17        i[n] = i[n]+1 
18        if (check(n)){
19            scan(n+1
20        }
 
21    }
 
22}
 
23
24 function check(n)
25    for (var j=0; j<n;j++)
26        if (i[j]==i[n] || i[j]-i[n]==j-|| i[j]-i[n]==n-j )
27            return false  
28    return true 
29}
 






运行结果是: time used:1241
比groovy快了5倍以上。groovy可真是够慢的。


把groovy编译的class文件反编译了一下,看到groovy生成的代码效率确实是太低了,我们就看循环最内层的check函数吧:


1 def check(n) {
2    if (n>0)
3        for (j in 0..<n) 
4            if (i[j]==i[n] || i[j]-i[n]==j-|| i[j]-i[n]==n-j )
5                return false
6    return true
7}


 


编译后变成



 1      public  Object check(Object obj)
 2      {
 3        if(ScriptBytecodeAdapter.compareGreaterThan(obj, new Integer(0)))
 4        {
 5            Object obj1 = null;
 6            for(Iterator iterator = ScriptBytecodeAdapter.asIterator(ScriptBytecodeAdapter.createRange(new Integer(0), obj, false)); iterator.hasNext();)
 7            {
 8                Object obj2 = iterator.next();
 9                Object obj3 = null;
10                if(ScriptBytecodeAdapter.asBool(ScriptBytecodeAdapter.asBool(ScriptBytecodeAdapter.compareEqual(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this"i"), "getAt", ((Object) (new Object[] {
11    obj2
12}
))), ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this"i"), "getAt", ((Object) (new Object[] {
13    obj
14}
)))) || ScriptBytecodeAdapter.compareEqual(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this"i"), "getAt", ((Object) (new Object[] {
15    obj2
16}
))), "minus", ((Object) (new Object[] {
17    ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this"i"), "getAt", ((Object) (new Object[] {
18        obj
19    }
)))
20}
))), ScriptBytecodeAdapter.invokeMethod(obj2, "minus", ((Object) (new Object[] {
21    obj
22}
)))) ? ((Object) (Boolean.TRUE)) : ((Object) (Boolean.FALSE))) || ScriptBytecodeAdapter.compareEqual(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this"i"), "getAt", ((Object) (new Object[] {
23    obj2
24}
))), "minus", ((Object) (new Object[] {
25    ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this"i"), "getAt", ((Object) (new Object[] {
26        obj
27    }
)))
28}
))), ScriptBytecodeAdapter.invokeMethod(obj, "minus", ((Object) (new Object[] {
29    obj2
30}
)))) ? ((Object) (Boolean.TRUE)) : ((Object) (Boolean.FALSE))))
31                    return Boolean.FALSE;
32            }

33
34        }

35        return Boolean.TRUE;
36    }

37




 

一切都是object,做任何事情都是invokeMethod,两个整数的比较居然要写将近400个字符的代码,光看代码量都可以吓倒我了。这是我们期待的脚本语言吗?


groovy可以嵌入到java代码里面,但是java代码可以嵌入到groovy里面吗?我觉得groovy有必要提供这样一种机制,在有必要的时候可以消除性能瓶颈。可是现在只看到groovy里面可以通过Scriptom(现在还是beta版)嵌入vbs、js脚本(包括使用WSH,FSO)或者调用InternetExplorer、Media Player、Word和Excel等windows组件。看来对消除性能瓶颈的帮助不大。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值