MRIとRubiniusで排他制御
はじめに
Matz's Ruby Interpreter(MRI)とRubiniusで排他制御したマルチスレッドプログラムを実行し、結果を比較します。
実行時間計測、CPUコア使用状況を見ていきます。
の4つを比較します。
準備
- 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 1000000.times do variable += 1 end end end threads.each(&:join) puts variable
- 検証に用いる排他制御ありのプログラム
variable = 0 mutex = Mutex.new threads = 5.times.map do Thread.new do 1000000.times do mutex.synchronize do variable += 1 end end end end threads.each(&:join) puts variable
メインスレッド以外にスレッドを5つ作成し、
それぞれのスレッドで百万回、足し合わせる処理を行います。
Mutexクラスのsynchronizeメソッドで排他制御します。
MRIの実行結果 排他制御なし
- 実行時間計測
$ time ruby multi_thread.rb 5000000 real 0m0.500s user 0m0.476s sys 0m0.020s
はやいです。
topコマンドしても意味ないくらい一瞬です。
- CPUコア使用状況
%Cpu0 : 14.8 us, 2.7 sy, 0.0 ni, 82.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 5.7 us, 1.7 sy, 0.0 ni, 92.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 6.7 us, 0.7 sy, 0.0 ni, 92.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 6.8 us, 0.7 sy, 0.0 ni, 92.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 3957672 total, 1806896 used, 2150776 free, 100764 buffers KiB Swap: 4104188 total, 0 used, 4104188 free, 864556 cached
topコマンドから1を押すとコアごとのCPU使用率を見ることができます。
MRIの実行結果 排他制御あり
- 実行時間計測
$ time ruby synchronized_multi_thread.rb 5000000 real 0m57.339s user 0m30.708s sys 1m20.836s
遅くなりました。
後述のRubinius排他ありと同じくらい時間かかります。
システム時間に大分かかってますね。
- CPUコア使用状況
Tasks: 232 total, 1 running, 231 sleeping, 0 stopped, 0 zombie %Cpu0 : 16.2 us, 36.9 sy, 0.0 ni, 46.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 17.5 us, 32.8 sy, 0.0 ni, 49.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 11.5 us, 31.0 sy, 0.0 ni, 57.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 13.8 us, 30.5 sy, 0.0 ni, 55.3 id, 0.0 wa, 0.0 hi, 0.4 si, 0.0 st KiB Mem: 3957672 total, 1791912 used, 2165760 free, 100168 buffers KiB Swap: 4104188 total, 0 used, 4104188 free, 858356 cached
Rubiniusの実行結果 排他制御なし
- 実行時間計測
$ time rbx multi_thread.rb 2344231 real 0m1.903s user 0m6.032s sys 0m0.044s
- CPUコア使用状況
Tasks: 234 total, 1 running, 233 sleeping, 0 stopped, 0 zombie %Cpu0 : 46.3 us, 1.7 sy, 0.0 ni, 52.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 48.3 us, 1.0 sy, 0.0 ni, 50.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 60.1 us, 1.3 sy, 0.0 ni, 38.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 48.2 us, 0.3 sy, 0.0 ni, 51.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 3957672 total, 1886912 used, 2070760 free, 101468 buffers KiB Swap: 4104188 total, 0 used, 4104188 free, 890144 cached
コアをたくさん使用してますね。
Rubiniusの実行結果 排他制御あり
- 実行時間計測
$ time rbx synchronized_multi_thread.rb 5000000 real 0m54.607s user 0m46.080s sys 1m9.592s
MRI排他制御ありと同じくらい時間かかりました。
競合もしていません。
- CPUコア使用状況
Tasks: 234 total, 1 running, 233 sleeping, 0 stopped, 0 zombie %Cpu0 : 23.4 us, 30.9 sy, 0.0 ni, 45.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 22.0 us, 33.2 sy, 0.0 ni, 44.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 18.6 us, 28.8 sy, 0.0 ni, 52.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 18.6 us, 27.0 sy, 0.0 ni, 54.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem: 3957672 total, 1991948 used, 1965724 free, 102420 buffers KiB Swap: 4104188 total, 0 used, 4104188 free, 904304 cached
排他制御していない時と比べると活用率は下がりますね。