8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

言語/処理系ベンチマーク(C++,D,C#,VB,Node.js,WSH,Python3,HSP3,Lisp,Scheme,Clojure)

Last updated at Posted at 2018-05-13

いくつかの言語/処理系でベンチマークを行った。
内容自体は次の記事の物とほぼ同一だが、PCや実行環境の変化もあったことを理由とする。

パラレルベンチマーク [C++/D/C#/VB/JS/HSP/Python/Ruby]
言語/処理系ベンチマークまとめ
言語/処理系ベンチマーク たらい回し関数編

今まではベンチマークのソース内のみで速度の計測を行っていたが、今回は実装ごとのオーバーヘッド等も考慮するべくPowerShellのMeasure-Command関数で外側から計測を行った。

実装

下記より参照。
yosgspec/bench-langs: 多数言語/処理系でベンチマーク!

結果

単位は全てmsとする。また、赤色で表記される結果はマルチスレッドまたはマルチプロセスによる実行結果である。

fib(40)

fib40.png

tarai(12,6,0)

tarai1260.png

2,000,000,000インクリメント

2t.png

5,000,000,000インクリメント

5t.png

感想・考察

C++

VC++、Clang共に全体的にほぼ最速となっている。
特にインクリメントループでの最適化は大きく、おそらく置換も行われていそう。
ただし、int64型での計算ではVC++は最適化があまり機能しておらず.Net言語系よりも遅くなるという結果になった。

D言語

傾向はC++に近い。
fib(40)の時DMDで僅差で最速の記録を出しており速度も遜色ない。
LDCはコンパイラ部分にLLVMを使用しているためインクリメントループではClangと同様の最適化が施されている。
DMDは極端な最適化は働いていないが、int計算においては最速クラスだった。
しかし、VC++同様int64型の計算は苦手なようで順位を大きく落としていた。

C#

全体的に高速でネイティブ言語勢の次くらいの順位を占める。
int64における計算速度でも計算速度の低下は見られずネイティブ勢をも凌ぐ。
プラットフォーム間の比較としては
.Net Framework < .Net Core < Mono
であるが、.Net Frameworkと.Net Coreにおいては誤差と言えるくらいの速度差しかなく、代替してもパフォーマンスに問題がないことが分かった。
Monoについては明確に一回り遅くなっているが全体的に高レベルに位置している。

VB

実行環境はC#と変わらないのでさほどC#と変わらないが
最適化手法が異なるのか、わずかにC#より遅い。
なお、標準ではオーバーフローチェックを行うことが無効化されている。

C#Script

実行前にコンパイル処理を挟むせいか、一気に速度が落ちる。
一般的なインタプリタ言語よりも勝る程度。
JIT/AOTコンパイル勢には到底及ばない。

Node.js

.Net言語の次に速いグループに属し、極めて高速。
Promiseは非同期処理であるが、シングルスレッドであるため高速化には寄与しない。
並行処理を利用した高速化にはCluster(マルチプロセス)を使用する。
内部型にint64を持たないためか二つの加算ループ間の速度比が4倍以上と非常に大きな値となっていた。

以降、ChakraCore版について。
intを超えた加算ループでも大きな速度の低下が見られず(2.6倍差)、高速であった。
int64を内部で使用しているのかもしれない。
ただし、Promiseを使うと非常に遅くなった。
fib(40)とtarai(12,6,0)の結果を見るとV8版に比べて遅くなっており、関数呼び出しのオーバーヘッドが大きくなっている可能性が考えられる。

Python3

CPython

インタプリタ言語であるため非常に低速。
今回の比較の中では最低クラスのスコアである。
コンパイルによる速度の高速化も特に無いようだ。
ただし、高速化する手段が充実しており方法と次第ではC++を超えられることもあるという。
今回はその中のNumbaとPyPyで高速化を図った。

なお、マルチスレッドも可能なものの、GILという機構により高速化には寄与しない。
高速化にはマルチプロセスにする必要あり。

Numba

PythonをJITコンパイルしているとのことであるが、かなりの高速化が見られた。
特に加算ループについてはいずれのパターンでも最適化の程度は大きく変わらないようで、どれも同じような結果となった(マルチスレッドと明記しなくても早くなる)。
JITコンパイルを行うと処理によってはエラーが起きることもあるが、その場合は関数を分けてあげて該当処理だけJITコンパイルから取り除けば十分な恩恵は受けられる。

PyPy

Numbaと同様にJITコンパイルを行うが、NumbaがライブラリでPyPyが実行環境とアプローチが異なる。
Windows版ではマルチプロセスは実行不能であった。
NumbaとPyPyでは多少得意なことが異なるようで、fib(40)とtarai(12,6,0)で順位が入れ替わっていた。

HSP

インタプリタであるため遅い。早くHSPの組み込みでマルチスレッド実装されないかな。
マルチプロセスはexec使えばできないこともない。
なお、HSPにint64はないためその領域はdoubleで計算している。

WSH(JScript・VBS)

JScript・VBSともに大して変わらず遅い。
マルチスレッドも不可。
JScriptはエンジンをChakraにするとNode.js並みに速くなって凄い。

CommonLisp

処理系ごとで速度の傾向などは全く異なる。
CommonLispの仕様にはスレッドは含まれないが、どの実行環境もスレッドが独自で実装されている。
加算ループではループ法の比較も行った。

SBCL

速くて安定しているとよく聞くCL環境。
全体的に見るとJITコンパイル勢に若干劣るくらいの速度。
コンパイルでの速度はほぼ変わらない。

ループ法での速度はdotimes < loop for < doとなった。

CLISP

fib(40)、tarai(12,6,0)のみのスポット参戦。
コンパイル前では双方ともにビリ。
しかし、コンパイルすればそれなりの速さにはなる。

CCL

今回一番想定できていなかったダークホース。
全体的に高速で再帰関数ではNode.jsを超え.Net言語に迫る速度を出している。
ただし、ループ加算処理は少し苦手なのか順位を落とし、Node.jsよりも少し遅れを取っていた。

ループ法での速度の違いも特徴的でSBCLと傾向が全く異なり、loop for < do < dotimesとの順番となっている。
一方安定性という面では(quit)が必要なことや、ベンチマークの際にプログラムが閉じないこともあったり難があるのかもしれない。

速度という面ではCommonLisp一優秀な処理系と言っても問題はないと思う。
また、CommonLispでは型指定などによるチューニングも可能だと聞くのでそこまでやれば.Net勢くらいの速度は出せるかもしれない。

Scheme

Gauche・Sagittarius Schemeともにインタプリタ言語であるため、どちらも傾向は遅め。
Pythonよりも少し早いくらい。
僅差でGaucheの方が速い傾向(int64域ではSagittariusが勝る)。

Sagittariusのマルチint64ループが非常に遅かったのが気になる。
Gaucheのマルチスレッドループは何回回してもムラが激しく十数秒クラスで誤差が出ること多し。これは早かった時の結果を載せている。

スレッドはSRFI-18で共通の仕様があるが、import構文に差異があり同一のスクリプトファイルでは動かない模様。

Clojure

3種類の環境(JVM・CLR・JavaScript)で動作する。
どれも全体的に遅いが、傾向は結構異なっている。
一貫していえる傾向としてはCLRが飛びぬけて遅いことは間違いない。
傾向は処理系ごとにまとめる。

Clojure(Boot:JVM)

全体的に安定しているが、総合スコアではClojureScriptよりも下。
ループ法ではリスト生成しまくるforが最も早く、dotimesとloop/recurはほぼ大差なかった。

ClojureCLR

全てにおいてダントツの遅さ。
遅いのは知っていたけど、まさかPython以上だとは。
ただし、Windowsでは一番導入が簡単な処理系なので今後も僕は使うと思う。

ループ法による傾向では、dotimes << for < loop/recurという感じ。
Clojureの特徴でもある組み込みの再帰ループが一番遅いというのは意外。
処理系を選ばないコードを書くにはloopでなくdotimesを使うのが一番安定するということ。

ClojureScript(Node.js)

実質的にJavaScriptのトランスパイラなので変換先の影響を大きく受ける。
また、ClojureのサブセットでありClojure言語の一部の機能を使うことができない代わりにjsやNodeのAPIを使用できる。

処理速度はNode.jsの能力に引っ張られているからかfib(40)とtarai(12,6,0)ではJVM以上の速度を誇る。
一方、ループ加算処理ではNode.jsの傾向通りに後れを取ってしまった。
(int計算のチューニングがなされないため、おそらくdoubleで計算している)

なお、forはリスト生成の処理で何か問題があるのか1時間以上待っても処理が終了しなかった。そのため、測定不能で値を9999999msとしている。
また、JavaScriptはマルチスレッドが使用できないためかfutureの仕様ができなかったため、Node.js APIのclusterモジュールでマルチプロセスを計測した。

全体

C++、D言語などネイティブ言語勢が最速になるというのは初めから想定通り。
その次に中間言語の.Net、Node.js、Numba、PyPy、CCL(AOT?)などJITコンパイル系、
SBCL(AOT)あたりを境界にHSP、WSH、CPython、その他Lisp系といったインタプリタ言語が来るようになっていた。
今回のベンチマークで驚いた点はCCLがNode.jsと対等に渡り合えるぐらいの速度を持っていたことだった。

次に今回のベンチマークをスコアで表したものを示す。
計算式は次のようになっている。
処理系数x8-(fib(40)順位+tarai(12,6,0)順位)x2-(int加算ループシングル順位+int加算ループ最速順位+int64加算ループシングル順位+int64加算ループ最速順位)

C++ Clang 252
Dlang LDC 240
C++ VC++ 228
C# .Net Framework 223
Dlang DMD 216
VB .Net Framework 216
C# .Net Core 207
VB .Net Core 203
C# Mono 179
VB Mono 179
CommonLisp CCL 163
JavaScript Node.js(uglifyjs) 158
Python3 CPython(Numba:pyc) 157
Python3 CPython(Numba) 154
JavaScript Node.js 152
JavaScript Node.js(ChakraCore) 147
JavaScript JScript(WSH:Chakra) 138
CommonLisp SBCL(fasl) 125
CommonLisp SBCL 123
Python3 PyPy 110
CommonLisp CLISP(fas) 104
C#Script .Net Framework 96
Clojure Lumo(Script) 80
Clojure Boot(JVM) 76
Scheme Gauche 75
CommonLisp CLISP 68
Scheme Sagittarius Scheme 67
Python3 CPython 50
HSP3 HSP3(mist) 50
Python3 CPython(pyc) 48
Clojure CLR 28
VBScript VBScript(WSH) 27
JavaScript JScript(WSH) 19

全ての結果

言語 処理系 fib(40)[ms] tarai(12,6,0)[ms] インクリメント2000000000 インクリメント5000000000
シングルスレッドその1 シングルスレッドその2 シングルスレッドその3 マルチスレッド・プロセスその1 マルチスレッド・プロセスその2 マルチスレッド・プロセスその3 シングルスレッドその1 シングルスレッドその2 シングルスレッドその3 マルチスレッド・プロセスその1 マルチスレッド・プロセスその2 マルチスレッド・プロセスその3
方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] 方法 タイム[ms] fib(40) tarai(12,6,0) シングル マルチ 最速 シングル マルチ 最速 fib(40) tarai(12,6,0) シングル 最速 シングル 最速
C++ VC++ 499 32 for 11 future 13 parallel for(OpenMP) 17 for 3567 future 972 parallel for(OpenMP) 976 11 13 11 3567 972 972 324.27 2 2 2 2 2 13 11 11 228 3.91 3.91 830.18 251.64 6.38 6.94
C++ Clang 549 30 for 10 future 12 parallel for(OpenMP) 10 for 10 future 10 parallel for(OpenMP) 10 10 10 10 10 10 10 1.00 3 1 1 1 1 1 1 1 252 3.55 4.17 913.20 276.80 2,275.20 674.10
Dlang DMD 478 44 for 598 Thread 174 parallel foreach 174 for 3562 Thread 2367 parallel foreach 2349 598 174 174 3562 2349 2349 5.96 1 4 6 4 4 12 16 16 216 4.08 2.84 15.27 15.91 6.39 2.87
Dlang LDC 556 40 for 20 Thread 21 parallel foreach 18 for 19 Thread 19 parallel foreach 18 20 18 18 19 18 18 0.95 4 3 3 3 3 2 2 2 240 3.51 3.13 456.60 153.78 1,197.47 374.50
C# .Net Framework 664 53 for 601 Task 184 Parallel.For 184 for 1446 Task 412 Parallel.For 413 601 184 184 1446 412 412 2.41 5 5 8 5 5 5 3 3 223 2.94 2.36 15.19 15.04 15.73 16.36
C#Script .Net Framework 4394 988 for 8094 Task 1897 Parallel.For 1869 for 18156 Task 3284 Parallel.For 3213 8094 1869 1869 18156 3213 3213 2.24 23 25 19 17 17 19 17 17 96 0.44 0.13 1.13 1.48 1.25 2.10
C# .Net Core 684 72 for 616 Task 204 Parallel.For 208 for 1466 Task 435 Parallel.For 436 616 204 204 1466 435 435 2.38 6 7 10 8 8 7 6 6 207 2.85 1.74 14.82 13.57 15.52 15.50
C# Mono 790 138 for 816 Task 316 Parallel.For 429 for 2946 Task 606 Parallel.For 887 816 316 316 2946 606 606 3.61 9 13 11 10 10 10 10 10 179 2.47 0.91 11.19 8.76 7.72 11.12
VB .Net Framework 771 58 For 598 Task 186 Parallel.For 186 For 1448 Task 418 Parallel.For 414 598 186 186 1448 414 414 2.42 7 6 6 6 6 6 4 4 216 2.53 2.16 15.27 14.88 15.71 16.28
VB .Net Core 785 73 For 613 Task 203 Parallel.For 206 For 2881 Task 433 Parallel.For 436 613 203 203 2881 433 433 4.70 8 8 9 7 7 8 5 5 203 2.48 1.71 14.90 13.64 7.90 15.57
VB Mono 826 140 For 1245 Task 278 Parallel.For 281 For 2945 Task 514 Parallel.For 508 1245 278 278 2945 508 508 2.37 10 14 12 9 9 9 7 7 179 2.36 0.89 7.33 9.96 7.73 13.27
JavaScript Node.js 1119 164 for 1318 Promise 1294 cluster 539 for 5611 Promise 5625 cluster 1384 1294 539 539 5611 1384 1384 4.34 13 16 15 11 11 15 13 13 152 1.74 0.76 7.06 5.14 4.05 4.87
JavaScript Node.js(uglifyjs) 1114 162 for 1356 Promise 1293 cluster 542 for 5605 Promise 5594 cluster 1377 1293 542 542 5594 1377 1377 4.33 12 15 14 12 12 14 12 12 158 1.75 0.77 7.06 5.11 4.07 4.90
JavaScript Node.js(ChakraCore) 1347 242 for 1262 Promise 2370 cluster 646 for 3291 Promise 19546 cluster 1387 1262 646 646 3291 1387 1387 2.61 15 17 13 15 15 11 14 14 147 1.45 0.52 7.24 4.28 6.91 4.86
JavaScript JScript(WSH) 63070 2369 for 378148 for 617148 378148 378148 617148 617148 1.63 31 30 31 31 30 31 19 0.03 0.05 0.02 0.01 0.04 0.01
JavaScript JScript(WSH:Chakra) 1120 118 for 6389 for 17917 6389 6389 17917 17917 2.80 14 10 18 21 18 21 138 1.74 1.06 1.43 0.43 1.27 0.38
VBScript VBScript(WSH) 69541 2857 For 169958 For 444803 169958 169958 444803 444803 2.62 32 31 27 30 25 29 27 0.03 0.04 0.05 0.02 0.05 0.02
Python3 CPython 44855 1659 for 223812 future Thread 128644 future Process 34478 for 548088 future Thread 337956 future Process 87639 223812 34478 34478 548088 87639 87639 2.45 28 26 29 25 26 27 23 24 50 0.04 0.08 0.04 0.08 0.04 0.08
Python3 CPython(Numba) 1421 645 for 569 future Thread 557 future Process 561 for 572 future Thread 586 future Process 562 569 557 557 572 562 562 1.01 17 23 4 13 13 4 9 9 154 1.37 0.19 16.05 4.97 39.78 11.99
Python3 PyPy 2113 393 for 3524 future Thread 3638 for 8587 future Thread 8510 future Process 3524 3638 3524 8587 8510 8510 2.44 21 19 17 20 20 17 20 20 110 0.92 0.32 2.59 0.79 2.65 0.79
Python3 CPython(pyc) 44293 1674 for 233142 future Thread 121902 future Process 34380 for 591483 future Thread 340805 future Process 88069 233142 34380 34380 591483 88069 88069 2.54 27 27 30 24 25 28 24 25 48 0.04 0.07 0.04 0.08 0.04 0.08
Python3 CPython(Numba:pyc) 1364 645 for 571 future Thread 557 future Process 560 for 564 future Thread 583 future Process 561 571 557 557 564 561 561 0.99 16 23 5 13 13 3 8 8 157 1.43 0.19 15.99 4.97 40.34 12.02
HSP3 HSP3(mist) 50120 2242 repeat 68703 for 230619 mstThread 37222 repeat 178960 while 670926 mstThread 86441 68703 37222 37222 178960 86441 86441 2.60 29 29 25 26 27 23 22 23 50 0.04 0.06 0.13 0.07 0.13 0.08
CommonLisp SBCL 1950 125 dotimes 9132 loop for 13438 do 14219 sb-thread dotimes 2768 sb-thread loop for 3261 sb-thread do 3563 dotimes 22752 loop for 31268 do 35497 sb-thread dotimes 6741 sb-thread loop for 8073 sb-thread do 8812 9132 2768 2768 22752 6741 6741 2.49 20 12 20 19 19 20 18 18 123 1.00 1.00 1.00 1.00 1.00 1.00
CommonLisp SBCL(fasl) 1949 123 dotimes 9816 loop for 12521 do 13098 sb-thread dotimes 2762 sb-thread loop for 3253 sb-thread do 3557 dotimes 24489 loop for 31745 do 32659 sb-thread dotimes 6784 sb-thread loop for 8059 sb-thread do 8812 9816 2762 2762 24489 6784 6784 2.49 19 11 21 18 18 21 19 19 125 1.00 1.02 0.93 1.00 0.93 0.99
CommonLisp CLISP 84496 3133 dotimes loop for do dotimes loop for do #VALUE! 33 32 x x 68 0.02 0.04 0.00 0.00 0.00 0.00
CommonLisp CLISP(fas) 18161 558 dotimes loop for do dotimes loop for do #VALUE! 26 21 x x 104 0.11 0.22 0.00 0.00 0.00 0.00
CommonLisp CCL 964 73 dotimes 6278 loop for 2593 do 5135 process dotimes 1723 process loop for 730 process do 1417 dotimes 15656 loop for 6417 do 12814 process dotimes 4233 process loop for 1759 process do 3474 2593 730 730 6417 1759 1759 2.47 11 8 16 16 16 16 15 15 163 2.02 1.71 3.52 3.79 3.55 3.83
Scheme Gauche 8454 387 do 42334 let loop 41368 SRFI-18 thread 23295 do 680936 let loop 692058 SRFI-18 thread 395387 41368 23295 23295 680936 395387 395387 16.46 24 18 23 22 23 31 27 28 75 0.23 0.32 0.22 0.12 0.03 0.02
Scheme Sagittarius Scheme 10494 442 do 45980 let loop 47010 SRFI-18 thread 27741 do 609288 let loop 607874 SRFI-18 thread 1663570 45980 27741 27741 607874 1663570 607874 13.22 25 20 24 23 24 29 28 30 67 0.19 0.28 0.20 0.10 0.04 0.01
Clojure Boot(JVM) 3422 1936 dotimes 30847 loop 30607 reduce for 19277 future for 8641 pmap 8603 dotimes 73138 loop 74055 reduce for 43604 future for 18340 pmap for 18362 19277 8603 8603 43604 18340 18340 2.26 22 28 22 21 22 22 21 22 76 0.57 0.06 0.47 0.32 0.52 0.37
Clojure CLR 57852 3177 dotimes 190603 loop 335500 reduce for 308326 future for 104617 pmap 103016 dotimes 468098 loop 826022 reduce for 766387 future for 257496 pmap for 254110 190603 103016 103016 468098 254110 254110 2.46 30 33 28 28 29 26 26 27 28 0.03 0.04 0.05 0.03 0.05 0.03
Clojure Lumo(Script) 1790 590 dotimes 135896 loop 135669 reduce for 9999999 cluster dotimes 54642 dotimes 243845 loop 243748 reduce for 9999999 cluster dotimes 134532 135669 54642 54642 243748 134532 134532 1.80 18 22 26 27 28 24 25 26 80 1.09 0.21 0.07 0.05 0.09 0.05

実行環境

  • Windows 10 Home(x64)
  • Intel(R) Core(TM) i5-6500 @ 3.20GHz (Core4)
  • C++
    • cl: Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24210 for x86
    • clang: clang version 5.0.1 (tags/RELEASE_501/final)
  • Dlang
    • dmd: DMD32 D Compiler v2.080.0
    • ldmd2: LDC - the LLVM D compiler (1.9.0)
  • .Net
    • .NET Framework 4.7.1
      • csc: Microsoft (R) Visual C# Compiler バージョン 2.4.0.62225 (f0cdbe92)
      • csi: Microsoft (R) Visual C# インタラクティブ コンパイラ バージョン 2.4.0.62225
      • vbc: Microsoft (R) Visual Basic Compiler バージョン 2.4.0.62225 (f0cdbe92)
    • dotnet: .NET コマンド ライン ツール (2.1.105)
    • mono, dmcs: Mono JIT compiler version 5.10.1 (Visual Studio built mono)
  • Node.js(node)
    • Node.js v10.0.0
    • Node.js(chakraCore) v10.0.0
    • uglifyjs: uglify-es 3.3.9
  • cscript: Microsoft (R) Windows Script Host Version 5.812
  • HSP3.5
  • Python3
    • py -3: Python 3.6.4
    • pypy3: [PyPy 6.0.0 with MSC v.1910 32 bit] on win32(Python 3.5.3 (fdd60ed87e94, Apr 24 2018, 06:27:13))
  • CommonLisp
    • sbcl: SBCL 1.4.2
    • clisp: GNU CLISP 2.49 (2010-07-07)
    • wx86cl64(ccl): Version 1.11.5/v1.11.5 (WindowsX8664)
  • Scheme
    • gosh: Gauche scheme shell, version 0.9.5 [utf-8,wthreads], x86_64-pc-mingw64
    • sash: Sagittarius scheme shell, version 0.9.2 (x86_64-pc-win64)
  • Clojure
    • boot: Clojure(JVM)
    • Clojure.Main: ClojureCLR 1.8.0
    • lumo: ClojureScript
      • Lumo 1.9.0-alpha
      • ClojureScript 1.10.238
      • Node.js v9.10.0
8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?