前面的内容请看:Java、Scala和Go语言多线程并发对比测试。 相关的代码下载:http://qinhui99.itpub.net/resource/2570/31876
测试结果和结论
AMD 双核 2.8G ,4G内存 winxp
java+conc java+AKKA1.3 java+AKKA2.0 Scala+AKKA1.3 Scala+AKKA2.0 Go+goroutine
1-N 单位:秒
1000000 0.64 1.14 0.63 1.05 0.65 0.617
2000000 1.71 2.08 1.58 2.05 1.68 1.63
3000000 3.05 3.28 2.79 3.3 2.96 2.91
5000000 6.32 6.18 5.75 6.367 6.1 6.04
10000000 17.14 15.85 15.8 16.5 16.6 16.35
12000000 22.4 20.48 20.2 21.32 21.48 21.3
(由于AMD硬件平台性能很烂,测试时间较长,所以只测试到12000000)
INETL 平台 酷睿双核2.4G ,4G内存 winxp
java+concurrent java+AKKA1.3 java+AKKA2.0 Scala+ AKKA1.3 Scala+ AKKA2.0 Go+goroutine
1-N 单位:秒
1000000 0.209 0.87 0.235 0.73 0.219 0.28
2000000 0.53 1.12 0.48 0.98 0.485 0.54
5000000 1.93 2.19 1.55 2.08 1.61 1.65
10000000 4.93 4.62 4.09 4.57 4.1 4.18
20000000 13.25 11.14 10.95 11.13 10.92 10.98
30000000 23.24 19.37 19.13 19.25 19.35 19.39
测试真是又费时间又枯燥的事情。在两个硬件平台测试了之后,还有一个苹果系统的没有时间进行测试,先放着,等以后再补上吧。
性能测试结果说明:
1、 为了公平起见,各个组合的算法都是采用给多线程传递不变的参数,避免使用同步锁,尽量减少因为实现语言的不同而影响性能的因素。
2、 性能表现最好的前3个分别是:java+AKKA2.0,Scala+AKKA2.0,Go+goroutine。这3个组合的多线程并发计算指标比较接近。尽管在测试前,对Go语言报了很大期望,以为Go会是测试的冠军,但事实证明,对这个CPU密集运算的多线程并发测试案例来说,Go并不占优势,甚至不如java+AKKA2.0组合。这也证明了AKKA这个高性能并发运算框架果然很优异。不了解AKKA2.0的朋友,请访问:http://www.gtan.com/akka_doc/index.html。
3、 性能表现最常的是java+concurrent。当计算量小的时候,例如,1000000以下的时候,java+concurrent表现还不错。但计算量不断增大的时候,java+concurrent开始表现糟糕。在10000000以上的时候,java+concurrent表现更加糟糕。表现糟糕的原因可能是因为用到了 concurrent 的ExecutorService和Future。 Future其实是一种阻塞线程模式,所以性能并不是最佳。有时间读读AKKA2.0的源代码,也许能找到一些改进性能的参考办法。
4、 性能表现一般的是java+AKKA1.3和Scala+AKKA1.3。它们和AKKA2.0版本的最大差异是,它们采用的是发送并等待返回消息的阻塞模式,而AKKA2.0版本则采用发送就不管了的无阻塞模式。事实证明,阻塞模式比无阻塞模式性能要差不少。此外,尽管AKKA1.3的阻塞模式性能不好,但在大计算量的情况下表现仍然不错,和Go语言差不多,比java+concurrent要好。
5、 在运行java程序的时候,都加上了-server参数。而对于Scala和Go,我不了解该怎么优化,所以都只是使用Scala和Go普通的运行命令来启动程序。例如,
java -server org.aos.concurrent.samples.ConcurrentPrimeFinder 1000000 10 100
scala com.agiledeveloper.pcj.Primes 1000000 100
test_prime.exe -n=1000000 -workers=100
编程的难易程度测试结果说明:
1、 由于本人有多年的JAVA编程经验,所以java+concurrent组合是编码花费时间最少的。
2、 对于Scala和Go语言,本人学习的时间都差不多,3个星期左右。由于Scala和JAVA平台的互通性,也由于Scala平台的成熟和易用(开发工具和语法比Go好不少),所以开发Scala版本比Go版本所花费的时间要少。
3、 Scala+AKKA1.3比Scala+AKKA2.0版本更容易开发。因为Scala+AKKA1.3的阻塞模式容易理解,代码量也少。但阻塞模式在计算量比较大的时候,容易报timeout异常。需要增加一个akka.conf文件来定义更长的阻塞等待时间。对于Scala+AKKA2.0,AKKA官方提供了一个无阻塞模式的参考例子,采用master+worker+listener对象组合。Master分发多份工作给多个worker去计算, worker计算完后,分别把各自计算结果发回给master来汇总,最终,master把汇总结果发送给listener,并输出结果。为了使用这种对象组合,导致Scala+AKKA2.0版本的编码要比Scala+AKKA1.3版本复杂,花费的时间也相应要多些。另外,由于AKKA2.0采用无阻塞的模式,所以测试中没有出现过由于计算量大而出现的timeout问题。
4、 从Scala转到Java版本,确实有些困难,但幸好两个平台是互通的,并且有参考的例子,所以转过来也不是太困难。和Scala版本一样的,java+AKKA1.3版本比java+AKKA2.0版本要容易写些,也存在着阻塞模式的timeout问题。
5、 Go语言版本,由于和Java平台不互通,而且差异极大,编码花费时间最多。Go语言从Scala和Python等语言里获取了许多有益的东西,语法比较简洁,编译速度快,占用内存少,而且以goroutine的方式很方便地写出支持多线程并发计算的程序,确实很有发展前景。(在用过Scala和Go语言之后,真的很讨厌JAVA里面冗长的代码,特别是该死的分号‘;’)
但Go语言的缺陷也挺多的。这里就列几个测试所发现的情况:1)语言比较新,懂的人不多。这意味着学习成本和用人成本比较高;2)开发平台不成熟,在windows下安装配置Go的开发环境,本人的经历很痛苦。有一种当年用EditPlus写JAVA代码的感觉,很不爽。3)强类型转换,很烦人。为了使用math.Sqrt,居然逼我写了一段从float64转int的代码。在Java和Scala从未出现这样的情况。算是明白了,Go所谓的编译快其实就是程序员自己多付出点代价来照看代码。4)goroutine容易出现deadlock死锁现象。死锁的原因很多,让初学者头痛。
测试的最终结论:
综合性能测试和编码难易程度测试结果,本人从做项目的角度得出几点结论:
1、 对于Java程序员,如果没有强制性的必要,不需要转到Scala和Go语言,因为Java+AKKA2.0足够好用了,足以应付多线程高并发应用。
2、 对于Java程序员,如果程序应用于一般的多线程应用,并且性能要求不高,java的concurrent包也够用了。
3、 对于Java程序员,如果想让项目的代码量减少一半,学习成本不太高,性能也有保障的话,Scala语言是非常好的选择。
4、 对于Java程序员,如果项目时间有限,想要用Go语言来实现项目,那基本死路一条。
5、 对于Go语言的未来,也许如Go编程语言QQ群里的朋友所说的那样,在云计算领域可能会大放光彩。
由于能力、精力和资源有限,这次比较测试并不完美,可能存在不少问题。欢迎有兴趣的朋友讨论并发表意见。
相关的代码下载:http://qinhui99.itpub.net/resource/2570/31876