第一篇笔记里面,我说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-n?||?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-n?||?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-n?||?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-n?||?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,?((Object)?(new?Object[]? { 13 ????obj 14
 }))))?||?ScriptBytecodeAdapter.compareEqual(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this,?((Object)?(new?Object[]? { 15 ????obj2 16
 }))),?"minus",?((Object)?(new?Object[]? { 17
 ????ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this,?((Object)?(new?Object[]? { 18 ????????obj 19 ????}))) 20
 }))),?ScriptBytecodeAdapter.invokeMethod(obj2,?((Object)?(new?Object[]? { 21 ????obj 22
 }))))???((Object)?(Boolean.TRUE))?:?((Object)?(Boolean.FALSE)))?||?ScriptBytecodeAdapter.compareEqual(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this,?((Object)?(new?Object[]? { 23 ????obj2 24
 }))),?((Object)?(new?Object[]? { 25
 ????ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.getGroovyObjectProperty(this,?((Object)?(new?Object[]? { 26 ????????obj 27 ????}))) 28
 }))),?ScriptBytecodeAdapter.invokeMethod(obj,?((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组件。看来对消除性能瓶颈的帮助不大。
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|