AMD双核2.8G ,4G内存winxp
java+concjava+AKKA1.3java+AKKA2.0Scala+AKKA1.3Scala+AKKA2.0Go+goroutine
1-N
单位:秒
10000000.641.140.631.050.650.617
20000001.712.081.582.051.681.63
30000003.053.282.793.32.962.91
50000006.326.185.756.3676.16.04
10000000 17.1415.8515.816.516.616.35
12000000 22.420.4820.221.3221.4821.3
(由于AMD硬件平台性能很烂,测试时间较长,所以只测试到12000000)
INETL平台酷睿双核2.4G,4G内存winxp
java+concurrentjava+AKKA1.3java+AKKA2.0Scala+ AKKA1.3Scala+ AKKA2.0Go+goroutine
1-N单位:秒
10000000.2090.870.2350.730.2190.28
20000000.531.120.480.980.4850.54
50000001.932.191.552.081.611.65
100000004.934.624.094.574.14.18
2000000013.2511.1410.9511.1310.9210.98
3000000023.2419.3719.1319.2519.3519.39
测试真是又费时间又枯燥的事情。在两个硬件平台测试了之后,还有一个苹果系统的没有时间进行测试,先放着,等以后再补上吧。
性能测试结果说明:
1、为了公平起见,各个组合的算法都是采用给多线程传递不变的参数,避免使用同步锁,尽量减少因为实现语言的不同而影响性能的因素。
2、性能表现最好的前3个分别是:java+AKKA2.0,Scala+AKKA2.0,Go+goroutine。这3个组合的多线程并发计算指标比较接近。尽管在测试前,对Go语言报了很大期望,以为Go会是测试的冠军,但事实证明,对这个CPU密集运算的多线程并发测试案例来说,Go并不占优势,甚至不如java+AKKA2.0组合。这也证明了AKKA这个高性能并发运算框架果然很优异。不了解AKKA2.0的朋友,请访问:/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群里的朋友所说的那样,在云计算领域可能会大放光彩。
由于能力、精力和资源有限,这次比较测试并不完美,可能存在不少问题。欢迎有兴趣的朋友讨论并发表意见。
有疑问加站长微信联系(非本文作者)