MRIとRubiniusでマルチスレッド
はじめに
Matz's Ruby Interpreter(MRI)とRubiniusでマルチスレッドプログラムを実行し、結果を比較します。
実行時間計測、CPUコア使用状況を見ていきます。
複数回実行して、平均を取るなど真面目に検証はしていません。
準備
- Rubyのバージョン
$ ruby -v ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux]
- Rubiniusのバージョン
$ rbx -v rubinius 2.2.6.n110 (2.1.0 c004ced8 2014-04-20 JI) [x86_64-linux-gnu]
Rubiniusのインストールはこちらから
http://rubini.us/doc/ja/getting-started/building/
- 検証に用いるプログラム
variable = 0 threads = 5.times.map do Thread.new do 100000000.times do variable += 1 end end end threads.each(&:join) puts variable
メインスレッド以外にスレッドを5つ作成し、
それぞれのスレッドで1億回、足し合わせる処理を行います。
スレッドセーフではありません。
Rubyの実行結果
- 実行時間計測
$ time ruby multi_thread.rb 500000000 real 0m43.034s user 0m42.688s sys 0m0.052s
MRIはGVLが実装されているので、競合状態は発生しないですね。
- CPUコア使用状況
Tasks: 235 total, 1 running, 234 sleeping, 0 stopped, 0 zombie %Cpu0 : 45.6 us, 0.3 sy, 0.0 ni, 54.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 5.4 us, 0.7 sy, 0.0 ni, 94.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 20.3 us, 2.3 sy, 0.0 ni, 77.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 41.6 us, 0.3 sy, 0.0 ni, 58.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 3957672 total, 2745588 used, 1212084 free, 220392 buffers KiB Swap: 4104188 total, 0 used, 4104188 free, 1298312 cached
topコマンドから1を押すとコアごとのCPU使用率を見ることができます。
Rubiniusの実行結果
- 実行時間計測
$ time rbx multi_thread.rb 198985546 real 6m1.643s user 22m39.488s sys 0m1.408s
MRIと比較すると遅いです。
競合しまくりです。
スレッドセーフでないプログラムを作成したかいがありました。
マルチスレッドの場合、user値は合計値になるのでreal値よりも大きくなることがあるのですね。
- CPUコア使用状況
Tasks: 234 total, 1 running, 233 sleeping, 0 stopped, 0 zombie %Cpu0 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 99.7 us, 0.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 99.7 us, 0.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 3957672 total, 2120944 used, 1836728 free, 205068 buffers KiB Swap: 4104188 total, 0 used, 4104188 free, 998288 cached
コアをたくさん使用してます。