2007-12-27

今天做了个小实验,关于Groovy性能

关键字: groovy
//使用groovy的语法去编写
long time = System.currentTimeMillis()
10000.times {
int i = 0;
1000.times{ val->
i += val
}
}
println "${System.currentTimeMillis() - time} ms"

//使用Java的语法去编写
time = System.currentTimeMillis();
int i = 0;
for(int x= 1;x<10000;x++) {
for(int y=1;y<1000;y++) {
i=i+y;
}
}
System.out.println(i + " " + (System.currentTimeMillis() - time) +" ms");

执行结果分别是:
700032704 14531 ms
700032704 15875 ms

而第二部分代码写在Java类中的执行结果是:
700032704 16 ms


能基本说明两个问题,一,在Groovy中使用Java的语法,不会带来性能上的提升;二,Groovy在运行性能上和Java还是有较大差距的。

同样的逻辑,使用Ruby1.9,执行时间为3578.0 ms。

这样的结果我不甘心,于是,我在Groovy中调用了Java的代码:
time = System.currentTimeMillis()
JavaTest.main(null);
println "${System.currentTimeMillis() - time} ms"

执行结果还是700032704 16 ms。呵呵,看来如果需要进行大数据量的运算,还是先写到Java中吧,好在Groovy可以直接调用Java的代码。
评论
helian 2008-05-08
测试了一下各种循环,发现for in是最快的。
cfly 2008-01-13
对“拿int的计算来证明语言的计算能力”这种行为表示质疑。
魔力猫咪 2008-01-12
其实我最初是看到他的测试不太科学,说让他看看Grails网站做的Grails和rails的对比测试。虽然是Grails自己做的,但是既然敢放出来,那么就多少有些可信。结果被骂了(那个帖子已经被删了),就在自己的机器上重复了他的测试。以此证明他的测试误差比较大,如果用来做严谨的性能测试,无法得到正确结果。而且选择的测试用例也不太合适。结果他反以为我要证明Groovy和Java速度一样。结果就这么吵了下来。
Eric_liu 2008-01-11
tedeyang 写道
看两位在争吵,我唯一的收获就是知道了还有p-unit这东西。
谢谢,
一般我在性能测试的时候也是用System.currentTimeMillis()来做的。
我觉得误差问题也不会太大。

Groovy在数值计算上的速度确实太低了,JavaScript要远远比它快。
不过这样猛烈的数值计算一般用不到,还好,呵呵。


我和这位老兄一样.知道了p-unit这么好玩好用的一个东西.哈哈
tedeyang 2008-01-10
看两位在争吵,我唯一的收获就是知道了还有p-unit这东西。
谢谢,
一般我在性能测试的时候也是用System.currentTimeMillis()来做的。
我觉得误差问题也不会太大。

Groovy在数值计算上的速度确实太低了,JavaScript要远远比它快。
不过这样猛烈的数值计算一般用不到,还好,呵呵。
geszJava 2008-01-10
groovy的简单值处理有待提高.至少需要到达rails这种程度.
不过数值运算就不需要用groovy来搞了吧.
有哪位可以检测一下其他方面得东东,譬如函数调用的性能.
魔力猫咪 2008-01-04
下面是我今天上午用p-unit性能测试引擎做的测试。测试结果应该是比较精确的。还是我那台机器,测试了四次。groovy是用groovyc编译成Java代码测试的。

Goo.groovy
int i=0
for (int x in 1..10000) {
    for (int y in 1..1000) {
        i+=y
    }
}


Joo.java
public class Joo {
	public void begin() {
		int i = 0; 
		for (int x = 1;x <= 10000;x++) { 
			for (int y = 1;y <= 1000;y++) { 
				i = i + y;
			}
		}
	}
}


TestClass.test
import groovy.lang.Script;
import org.punit.runner.SoloRunner;
public class TestClass {

	public void testGoo() {
		Script g = new Goo(); 
		g.run();
	}
	
	public void testJoo(){
		Joo j = new Joo();
		j.begin();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		new SoloRunner().run(TestClass.class);
	}

}


下面是测试结果。
[solo] Starting TestClass
TestClass
testGoo() - [11809.302021ms]
testJoo() - [24.416232ms]
total: 2, failures:0 (GREEN) - 11868.730802ms

[solo] Starting TestClass
TestClass
testGoo() - [11783.037229ms]
testJoo() - [22.409552ms]
total: 2, failures:0 (GREEN) - 11840.076323ms

[solo] Starting TestClass
TestClass
testGoo() - [11668.793659ms]
testJoo() - [22.272384ms]
total: 2, failures:0 (GREEN) - 11727.853121ms

[solo] Starting TestClass
TestClass
testGoo() - [11584.613966ms]
testJoo() - [22.87693ms]
total: 2, failures:0 (GREEN) - 11643.096818ms

你可以看到两者的执行时间。testGoo测试的是groovy,testJoo测试的是Java。
魔力猫咪 2008-01-04
for(int x= 1;x<10000;x++) {
for(int y=1;y<1000;y++) {
我这么写,在Java里得到的数是6.....的。还是你代码错了。
其实我到底反对你哪里你也没搞明白。我主要反对的是你用这种方法做性能测试。用读取时间整型相减的方法测试是不科学的。像这种相差太大的测试,结论虽然不会错,但是得到的数据误差实在太大。我也说了,我做的时候,误差到了秒一级。
如果是在工作中,比较同一语言的两种算法的话,这种性能测试根本无法分辨性能差距。
我主要说的是这个问题。你虽然没有误导新手的意思,但是你的测试数据确实有肯能产生这种事情。所以说,性能测试不是随便写几个代码就出来的。
liangshixing 2008-01-03
更新了一下代码:
time = System.currentTimeMillis();
i = 0;
for(int x in 0..9999) {
for(int y in 0..999) {
i+=y;
}
}
System.out.println(i + " " + (System.currentTimeMillis() - time) +" ms");
确实比原来要快一倍,但不管怎么说,在Groovy中使用Java进行运算,是绝对正确的!
你在说我不对的时候,也有不少错误。是x<=10000和y<=1000,算出来的结果不正确的,逻辑都搞不正确还谈什么测试性能。
Groovy存在的价值更多的体现在它与Java的亲密关系上。不管什么高手老鸟,都不会介意在Groovy中用Java吧?
我的测试本身也不是用于比较Groovy和Java,我想比的是Ruby。我想说既然直接比比不过,就请Java出面好了。这是被你一步一步引入误区的!
魔力猫咪 2008-01-03
用对象计算是行为艺术?那BigDecimal呢?精确浮点运算你不用这个,保证误差哭死你。
动态语言比静态语言在速度上有数量级的差距是肯定的,没有人能说不对。我从来也没打算要证明groovy比java快(这是不可能的)。
我主要说的是你测试的结果不正确。性能测试不是这么来做的。我用重复你测试的办法,主要是要说明你测试的方法不正确。
首先,这种测试没有意义,用groovy最差的地方去和java最快的地方做对比,有意义吗?熟悉动态语言和静态语言的人都知道,两者的差距至少要有1个以上的数量级(20倍算少的)。其次,你的时间取值方法的误差太大,我用你的取值方式,误差达到秒级;再次,因为你测试用例有问题,两者的差距远没有你测试的那么大,我的groovy按照标准写法,性能立刻提高一倍。
你这种测试除了吓跑没接触过groovy的新手,严重误导大家对groovy的看法外,没有任何作用。因为你测出来的速度差距实在是超级大。
初学者是很难分析这些性能测试到底有什么意义的,他们只知道groovy比java慢800多倍。
结果在适合使用groovy等动态语言的地方,有了这种先入为主意识的人也会拒绝动态语言,他们的理由就是,groovy比java慢800多倍。
xyz20003 2008-01-03
我的结论是复杂数值计算用汇编。:D
liangshixing 2008-01-03
你是想用对象类型去搞数值计算?行为艺术吗?
我的结论是,在进行复杂数值计算是用Java去写。20倍的差距还小啊?算推翻我结论啦?
魔力猫咪 2008-01-02
好。你说我不能动摇你的实验。那我就动摇一下。还就用你的代码。不过你这种计时方式确实不科学。误差太大,无法准确记录程序实际消耗的时间。

首先,我说明一下我的环境,省得说我欺负你。
老IBM T40笔记本一台。PM1.5G,512M内存,30G4500转硬盘,独立显卡。装XPSP2系统。groovy是1.5.1,Java是6.0 update3。Java的环境是Eclipse3.3。机器因为装了太多IBM附带工具和金山2008杀毒软件,启动后内存占用约350M,Eclipse启动后,占用约500M。
首先是你在groovy中的程序。
//使用groovy的语法去编写
long time = System.currentTimeMillis()
10000.times {
int i = 0;
1000.times{ val->
i += val
}
}
println "${System.currentTimeMillis() - time} ms"

//使用Java的语法去编写
time = System.currentTimeMillis();
int i = 0;
for(int x= 1;x<10000;x++) {
for(int y=1;y<1000;y++) {
i=i+y;
}
}
System.out.println(i + " " + (System.currentTimeMillis() - time) +" ms");
发现你java部分贴错了,是x<=10000和y<=1000。
这两个我的机器里执行,消耗在21000到23000ms之间。比你的慢,估计是机器的缘故。
但是,我发现你写得groovy循环不对,我没有在我找到的资料中发现你这种循环方法,所以我使用了标准的for循环。
long time = System.currentTimeMillis()
int i = 0;
for (int x in 1..10000 ) {
for (int y in 1..1000) {
i+=y;
}
}
println "${i},${System.currentTimeMillis() - time} ms";
不知道你哪里找的循环方法,我这是groovy标准的for循环。
编译后执行,710032704,11577 ms,没什么浮动
控制台执行,710032704,12177 ms,1000ms左右浮动
所以说,你的循环代码有问题,我按标准的写法,速度快了一倍。

然后说Java的执行
Eclipse环境下,纯Java代码消耗20到30ms。把int和long换成Integer和Long,约610 ms。

看看你原来的代码,在我的环境下,21000/30 = 700倍速度。
我修改的代码,11577/30 = 385倍速度。
我觉得用基本类型和对象去拼比较无赖,所以测了一个对象的,用Integer和Long代替了int和long,11577/610=18.97倍。以动态语言对静态语言,差10倍20倍的速度,不能算慢吧?
也就是说,跑这个代码,groovy最少可以做到java20分之一的速度。当然,因为采用了你这种不科学的计算,我的误差很大。
你也可以看到,控制台执行的时候,最低21000多,最高到过23000。误差约2秒。这种测试都能有这么大误差。可见计时的不精确。
你这个测试是“以groovy之短攻java之所长”。动态语言对于这种计算是最慢的。因为要每计算一次都要判断类型等工作。所以花费时间很长。但是即使如此,我也可以做到最低20倍速度差。总比你14000多对16,差约875倍小。
goodyang 2008-01-02
接受不了意见发什么帖子,这里不是一言堂
魔力猫咪 2007-12-28
可以肯定的是,Groovy绝对比Java要慢,而且要慢很多。不过有没有这里的差距,实在不好说。说实在的,这里没有写清楚Groovy的版本、Java的版本以及测试的环境。而且用System.currentTimeMillis()来取时间不可取。我曾经用这种方法实验过,无法实际反映花费的时间。

下面是国外的测试,比你的测试要好不少。你参考参考。
http://docs.codehaus.org/display/GRAILS/Grails+vs+Rails+Benchmark
agile_boy 2007-12-28
http://www.jroller.com/rants/entry/why_is_groovy_so_slow
其实关键要清楚自己的性能是在那里,Groovy并不是万能的灵丹妙药,关于why groovy is slow,在groovy的maillist也有讨论。
lordhong 2007-12-27
"进行大数据量的运算"当然是用JAVA或者C来写咯...
GROOVY要充分利用它DYNAMIC LANGUAGE的特性...发扬长处...
发表评论

提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则

您还没有登录,请登录后发表评论

liangshixing
搜索本博客
博客分类
最新评论