概要
Ruby 2.6 から JIT の機能が追加されました
簡単に説明すると Ruby の関数の一部コードを C 言語に変換しコンパイル -> 実行することで Ruby の処理を高速化できるという機能です (詳細はこちら)
今回は 2.6 のインストールから実際に JIT を有効にして Ruby スクリプトを実行してみました
環境
- Ubuntu 16.04 (on Vagrant)
- ruby 2.6.0p0
ruby 2.6 のインストール
rvm ではすでに 2.6 が公開されているので rvm を使ってインストールします
sudo apt -y install gnupg2
gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
\curl -sSL https://get.rvm.io | bash -s stable
/home/vagrant/.rvm/bin/rvm install ruby-2.6
/home/vagrant/.rvm/bin/rvm alias create default ruby-2.6.0
すでに .profile に PATH の追加はされているので再ログインしましょう
- ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]
こんな感じでバージョンが表示されれば OK です
試してみる
いろいろなコードを書いて MJIT を有効にした場合 (--jit
) とそうでない場合の速度がどうなるか試してみました
内容はすべて同じで 1 から 1 億までの数字を合計する処理になります
実験1
- vim test1.rb
puts 100000000.times.inject { |sum, i| sum + i }
time ruby test1.rb
real 0m6.942s
user 0m6.924s
sys 0m0.016s
time ruby --jit test1.rb
real 0m7.326s
user 0m13.856s
sys 0m0.432s
何回か試してみましたが JIT を有効にしたほうが時間がかかってしまいました
実験2
- vim test1.rb
def calc
sum = 0
100000000.times do |i|
sum = sum + i
end
return sum
end
puts calc
time ruby test2.rb
real 0m4.882s
user 0m4.860s
sys 0m0.012s
time ruby --jit test2.rb
real 0m4.959s
user 0m9.332s
sys 0m0.328s
これも JIT を有効にしたほうが若干遅い結果になってしまいました
inject を使わないで計算するほうが単純に早くなりました
実験3
- vim test3.rb
def calc(c)
sum = 0
c.times do |i|
sum = sum + i
end
return sum
end
puts calc(100000000)
time ruby test3.rb
real 0m4.861s
user 0m4.848s
sys 0m0.008s
time ruby --jit test3.rb
real 0m4.550s
user 0m8.544s
sys 0m0.308s
ループさせる回数を引数で取るようにしています
これで試したところ JIT を有効にしたほうが早くなりました
何度か試しても JIT を有効にしたほうが早かったので間違いないと思います
その他
実行時に --jit-verbose=2 --jit-save-temps
を指定すると JIT の処理を追いつつ生成された C のコードを /tmp
配下に保存することができます
デバッグしたいときに使いましょう
time ruby --jit --jit-verbose=2 --jit-save-temps test3.rb
最後に
いろいろなコードを書いて JIT を有効にした場合とそうでない場合で速度を比較してみました
書いてみてわかったこととしては
- すべてのケースで速くなるわけではない
- JIT に適したコーディングを意識する必要がありそう
この辺りは使用する場合に考える必要がありそうです
また試してはいないのですが C に変換しコンパイルする処理は gcc や clang を使っているようなので単純にマシンのスペックにも影響するかもしれません
少し前に inline を使った手法を紹介しましたが、2.6 以降であれば inline を使わずに高速化することができると思います
ただ MJIT は直接 C が書けるわけではないので直接 C のライブラリを使いたい場合などは inline を使う感じになると思います
そのあたりは使い分けかなと思います
0 件のコメント:
コメントを投稿