C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

Dart vs. JavaScript vs. Haskell vs. C++ // n-body benchmarking!!

Dart と JavaScriptHaskell と C++ で n-body (多体問題)のベンチマークしたよー。時間測定は全て time ちゃんです。

<※コメントにて runhaskell とコンパイル済みの .o 存在下の挙動について教えて頂き、 runhaskell について測りなおしました!>

結果と感想文

result graph

f:id:USAGI-WRP:20120321224032p:plain

※Dartのcheckedモードは実際にはグラフの右端から大幅にハミ出しています。
※ runhaskell は2時間ほど経っても完了しませんでした;w;

result table

測ったデータを記録している生のスプレッドシートはこちら。

以下は簡易版。

Language - Implement compile [sec] run [sec] compile+run [sec]
Haskell - GHC 7.4.1 / runhaskell 0 n/a(>12868) n/a(>12868)
Haskell - GHC 7.4.1 / ghc 1.35 21.31 22.66
C++ - GCC 4.6.3 / g++ -O3 0.22 9.87 10.09
C++ - GCC 4.6.3 / g++ -O0 0.12 33.42 33.54
JavaScript - V8 3.6.6.20 / d8 --nodebugger 0 57.82 57.82
Dart SDK(2011-03-17/continuous) / dart
production
0 172.75 172.75
Dart SDK(2011-03-17/continuous) / dart
checked
0 1906.31 1906.31
Dart SDK(2011-03-17/continuous) / frogc + JavaScript V8 3.6.6.20 / d8 0.85 84.33 85.18
感想文
  • うーん…、 Dart VM は思っていたよりは割と遅かった。
    • ちょっと期待して比較対象を張り切り過ぎた感が否めないので、後で Perl/Python/Ruby/PHP あたりのデータも追加しようかな・w・;
  • runhaskell が輝いて見える。 nbody の様な処理を runhaskell に投げちゃうといつまで経っても終わってくれない;w;
  • C++ かわいいよ C++

簡易版のグラフでは振りきれてしまっていますが、 dart --enable-type-checks は production モードに比べて11倍()も実行時間が必要でした。やはり checked モードは開発者向けのテスト、デバッグ専用としか考えられて居ないみたいですね。

production モードでも JavaScript の3倍もの実行時間を必要とするのは残念でした。この辺りはバックエンドにJava置いてるだけやん…という辺りから含めて、将来的に生でV8より高速にDart仮想マシンが実行される様になると嬉しいな。…遠そうだけど・w・;

生っぽいログ

Haskell - GHC 7.4.1 - runhaskell & ghc
% time ghc --make -O2 -XBangPatterns -threaded -rtsopts -optc-O3 nbody.hs -o nbody.hs.ghc-7.4.1-O2-XBangPatterns-threaded-rtsopts-optc-O3
(中略)
ghc --make -O2 -XBangPatterns -threaded -rtsopts -optc-O3 nbody.hs -o   1.35s user 0.11s system 88% cpu 1.653 total
^Crunhaskell -XBangPatterns nbody.hs 50000000  12868.61s user 38.10s system 100% cpu 3:34:52.09 total

※ runhaskell は現実的な測定時間内での完了は無理でした;w;

./nbody.hs.ghc-7.4.1-O2-XBangPatterns-threaded-rtsopts-optc-O3 +RTS -N1 -RTS   21.76s user 0.04s system 99% cpu 21.910 total
./nbody.hs.ghc-7.4.1-O2-XBangPatterns-threaded-rtsopts-optc-O3 +RTS -N2 -RTS   25.11s user 0.95s system 98% cpu 26.380 total
./nbody.hs.ghc-7.4.1-O2-XBangPatterns-threaded-rtsopts-optc-O3 +RTS -N3 -RTS   35.13s user 4.00s system 113% cpu 34.450 total
./nbody.hs.ghc-7.4.1-O2-XBangPatterns-threaded-rtsopts-optc-O3 +RTS -N4 -RTS   54.76s user 4.03s system 144% cpu 40.786 total
./nbody.hs.ghc-7.4.1-O2-XBangPatterns-threaded-rtsopts-optc-O3 +RTS -N8 -RTS   385.24s user 27.02s system 273% cpu 2:30.65 total
C++ - GCC 4.6.3 - g++
% time g++ -pipe -O3 -fomit-frame-pointer -march=native -lm -mfpmath=sse -msse2 --std=c++0x -mfpmath=sse -msse3 nbody.cpp -o nbody.cpp.g++-4.6.3-pipe-O3-fomit-frame-pointer-march=native-lm-mfpmath=sse-msse2--std=c++0x-mfpmath=sse-msse3 
g++ -pipe -O3 -fomit-frame-pointer -march=native -lm -mfpmath=sse -msse2       0.22s user 0.03s system 72% cpu 0.338 total
% time ./nbody.cpp.g++-4.6.3-pipe-O3-fomit-frame-pointer-march=native-lm-mfpmath=sse-msse2--std=c++0x-mfpmath=sse-msse3 50000000
-0.169075164
-0.169059907
 50000000  9.87s user 0.00s system 98% cpu 10.010 total
% time g++ -pipe -O2 -fomit-frame-pointer -march=native -lm -mfpmath=sse -msse2 --std=c++0x -mfpmath=sse -msse3 nbody.cpp -o nbody.cpp.g++-4.6.3-pipe-O2-fomit-frame-pointer-march=native-lm-mfpmath=sse-msse2--std=c++0x-mfpmath=sse-msse3 
g++ -pipe -O2 -fomit-frame-pointer -march=native -lm -mfpmath=sse -msse2       0.22s user 0.02s system 87% cpu 0.267 total
% time ./nbody.cpp.g++-4.6.3-pipe-O2-fomit-frame-pointer-march=native-lm-mfpmath=sse-msse2--std=c++0x-mfpmath=sse-msse3 50000000                                                                                                           
-0.169075164
-0.169059907
 50000000  9.87s user 0.00s system 99% cpu 9.875 total
% time g++ -std=c++0x nbody.cpp -o nbody.cpp.g++-4.6.3-std=c++0x
g++ -std=c++0x nbody.cpp -o nbody.cpp.g++-4.6.3-std=c++0x  0.12s user 0.03s system 79% cpu 0.196 total
% time ./nbody.cpp.g++-4.6.3-std=c++0x 50000000
-0.169075164
-0.169059907
./nbody.cpp.g++-4.6.3-std=c++0x 50000000  33.42s user 0.00s system 99% cpu 33.543 total
JavaScript - V8 - d8
d8 --nodebugger nbody.js -- 50000000  57.82s user 0.13s system 100% cpu 57.839 total
Dart - Dart SDK - dart
dart nbody.dart 50000000  172.75s user 0.02s system 99% cpu 2:52.97 total
dart --enable-type-checks nbody.dart 50000000  1906.31s user 0.75s system 99% cpu 31:47.39 total
Dart/JavaScript - Dart SDK/V8 - frogc/d8
frogc nbody.dart  0.85s user 0.03s system 92% cpu 0.949 total

※frogcで生成した.dar.jsはコマンドラインからのパラメーターを回収できなくなっていたので、ソース中に埋め込まれたデフォルトの定数値10000を直接50000000に書き換えてから以下は実行した。

d8 --nodebugger nbody.dart.js  84.33s user 0.19s system 100% cpu 1:24.01 total

ベンチマークテストを行った環境

OS: Arch Linux (x86_64) Kernel 3.2.9
CPU: AMD Phenom(tm) II X4 940
MEM: 8GB DDR2-800
DISK: tmpfs 4.0 [GB]

% uname -a            
Linux LH-MAIN 3.2.9-1-ARCH #1 SMP PREEMPT Thu Mar 1 09:31:13 CET 2012 x86_64 AMD Phenom(tm) II X4 940 Processor AuthenticAMD GNU/Linux
% ghc -V
The Glorious Glasgow Haskell Compilation System, version 7.4.1
% runhaskell --version
runghc 7.4.1
% g++ --version                                                         
g++ (GCC) 4.6.3
% d8   
V8 version 3.6.6.20 [console: dumb]

dart は 2011-03-17 に入手可能だった継続ビルド版のDart SDKに含まれるものを使用。
(dartには--version的な実装がまだ無い)