瑞士的金融软件工程师和创业者Alexander Temerev在github上创建了一个项目skynet ,用来测试各语言(框架)的多线程并行计算的性能,并得到了一些有用的数据。本文翻译整理自这个项目的说明。
测试并行性能的代码逻辑很简单:创建一个actor(goroutine,或者其它语言中类似的并发库),它会创建10个子actor,然后每个子actor再创建10个子actor,一直这样创建下去,直到创建了1百万个actor,每个actor包含一个唯一的数字(0到999999)。然后最底层的actor把它们的数字返回给父actor,父actor计算总和后再把结果返回给它的父actor,一直返回直到根actor,这样根actor的包含数字就是0到999999的和,结果应该为499999500000。
所以测试代码的逻辑就是并行计算0到999999的和,测试各种语言的并行库性能。
当然标题是不准确的,只是借用了这个项目的名称,1百万的线程不太可能在一台机器上创建,Alexander Temerev比较的是一些语言的并发框架的实现,聪明的读者应该明白项目性能测试的是什么东西,
它包括了Scala Actor、Scala-Future、Go、erlang、haskell、C# Core、C# TPL、RxJava、node-bluebird、python、rust等语言/框架的测试代码。所以大家不必吐槽标题中的"线程",其实比较的是异步编程模型的性能。
作者列出了在三种测试环境中性能结果:
测试环境一:垃圾的Macbook 12" '2015, Core M, OS X
Actors
- Scala/Akka: 6379 ms.
- Erlang (non-HIPE): 4414 ms.
- Erlang (HIPE): 3999 ms.
Coroutines / channels
- Haskell (GHC 7.10.3): 6181 ms.
- Go: 979 ms.
Futures / promises
- .NET Core: 650 ms.
- RxJava: 219 ms.
测试环境二:i7-4770, Win8.1
Actors
- Scala/Akka: 4419 ms
- Erlang (non-HIPE): 1700 ms.
Coroutines / channels
- Haskell (GHC 7.10.3): 2820 ms.
- Go: 629 ms.
- F# MailboxProcessor: 756ms. (should be faster?..)
Futures / promises
- .NET Core: Async (8 threads) 290 ms
- Node-bluebird (Promise) 285ms / 195ms (after warmup)
- .NET Full (TPL): 118 ms.
测试环境三:i7-4771, Ubuntu 15.10
- Scala/Akka: 1700-2700 ms
- Haskell (GHC 7.10.3): 41-44 ms
- Erlang (non-HIPE): 700-1100 ms
- Erlang (HIPE): 2100-3500 ms
- Go: 200-224 ms
根据上面不同的操作环境和硬件配置,你应该对各语言的并行计算的能力有一个初步的印象,你可以在你的硬件环境中测试相应的代码,
运行办法可以参照作者的说明:How to run