SlideShare a Scribd company logo
1 of 27
Download to read offline
A 
Just 
In 
Time 
Compiler 
for 
CRuby 
CRuby言語処理系向けJITコンパイラ 
Masahiro 
Ide 
Yokohama 
Na=onal 
University 
RubyKaigi 
2014 
2014年9月19日(金) 
1
Outline 
• Ruby 
• Just-­‐In-­‐Time(JIT) 
compiler 
• RuJIT: 
a 
JIT 
compiler 
for 
Ruby 
※あまり実装よりの内容ではありません 
また,CRubyの実装に詳しくない人でも分かる 
内容(にしたつもり)です. 
2
Ruby 
Language 
and 
Implementa=on 
• Ruby 
is 
a 
dynamically 
typed 
scrip=ng 
language 
– Support 
excep=on, 
garbage 
collec=on, 
con=nua=on 
– CRuby 
is 
Ruby 
interpreter 
in 
C 
(de 
facto 
standard 
implementa=on 
of 
Ruby) 
– Many 
Implementa=ons 
JRuby(Java), 
IRonRuby(.NET), 
Rubinius(Ruby), 
MRuby(C), 
Topaz(PyPy) 
– Numeric 
benchmarks 
10-­‐100 
=mes 
slower 
than 
C 
• Need 
to 
improve!!! 
3
CRuby 
Internal 
YARV 
bytecode 
#toplevel 
09 
putobject 
100 
11 
send 
:=mes, 
block 
17 
leave 
#block 
02 
putself 
03 
getdynamic 
i 
06 
send 
:puts, 
nil 
14 
leave 
Ruby 
code 
100.=mes 
do 
|i| 
puts 
i 
end 
Parser 
AST 
Bytecode 
Compiler 
Interpreter 
Memory 
Manager 
C 
library 
CPU 
4
HOW 
TO 
SPEEDUP 
RUBY 
1. Translate/Compile 
to 
low-­‐level 
language 
– プログラム実行中にコンパイル→ 
Just-­‐In-­‐Time(JIT) 
– プログラム実行前にコンパイル→Ahead-­‐Of-­‐Time(AOT) 
– Target 
• Java 
bytecode 
(JRuby), 
.NET 
CLR 
(IronRuby), 
LLVM 
IR(Rubinius) 
2. Speedup 
Interpreter 
– ディスパッチ方法の工夫 
– メソッドキャッシュ 
– … 
5
Outline 
• Ruby 
• Just-­‐In-­‐Time(JIT) 
compiler 
• RuJIT: 
a 
JIT 
compiler 
for 
Ruby 
– Design 
– Usage 
– Current 
status 
6
RuJIT 
• A 
Trace 
based 
JIT 
compiler 
for 
CRuby 
– Like 
Firefox’s 
javascript 
VM 
approach 
• Based 
on 
current 
version 
of 
CRuby 
• Started 
in 
April 
2014 
• More 
Speed, 
Speed, 
Speed 
– … 
but 
maintain 
compa=bility 
with 
current 
Ruby 
7
Implementa=on 
Strategies 
• Objec=ve 
– Improve 
Ruby’s 
performance 
• Development 
policy 
– Low 
development 
cost 
• 1 
person, 
2~3 
month 
– High 
extensibility 
• Easy 
to 
develop 
new 
op=miza=on 
techniques 
– 実用的なソフトウェア 
• いつかRubyのメインラインに 
→この方針に基づいて設計を行っている 
8
RuJIT 
overview 
RuJIT 
YARV 
bytecode 
#toplevel 
09 
putobject 
100 
11 
send 
:=mes, 
block 
17 
leave 
#block 
02 
putself 
03 
getdynamic 
i 
06 
send 
:puts, 
nil 
14 
leave 
Ruby 
code 
100.=mes 
do 
|i| 
puts 
i 
end 
Parser 
AST 
Bytecode 
Compiler 
Interpreter 
Memory 
Manager 
C 
library 
CPU 
Na=ve 
code 
9
RuJIT 
Design 
• Trace 
based 
JIT 
compiler 
– Detect 
hot 
path(e.g. 
loop) 
• Intermediate 
Representa=on 
(IR) 
for 
op=miza=on 
– Low 
level 
– Contain 
run=me 
informa=on 
• Na=ve 
Code 
translator 
– Use 
C 
compiler 
(GCC, 
clang) 
as 
backend 
10 
YARV 
Trace 
Selec=on 
Engine 
Trace 
Cache 
RuJIT 
Run=me 
CRuby 
Run=me 
IR 
Generator 
Op=mizer 
invoke 
Code 
Generator 
C 
Compiler 
Na=ve 
code 
Trace 
compile
トレース方式コンパイラの実行の流れ 
11 
def square(x)! 
return x * x! 
end! 
! 
i = 0; y = 0! 
while y < 100000! 
y += square(i)! 
i = i + 1! 
end
Construct 
trace 
def square(x)! 
return x * x! 
end! 
! 
i = 0; y = 0! 
while y < 100000! 
y += square(i)! 
i = i + 1! 
end 
12 
BB0: 
guard_method_redefine(Fixnum.*) 
guard_method_redefine(Fixnum.+) 
guard_method_redefine(Fixnum.<) 
BB1: 
guard_is_fixnum(i) 
push_frame 
# 
invoke 
square 
guard_method_redefine(Fixnum.*) 
tmp 
= 
fixnum_mul(i, 
i) 
pop_frame 
# 
leave 
square 
guard_method_redefine(Fixnum.+) 
y 
= 
fixnum_plus(y, 
tmp) 
guard_method_redefine(Fixnum.+) 
i 
= 
fixnum_plus(i, 
1) 
guard_method_redefine(Fixnum.<) 
tmp2 
= 
fixnum_lt(i, 
100000) 
guard_nil(tmp2) 
jump 
BB1 
トレース
Op=mize 
trace 
def square(x)! 
return x * x! 
end! 
! 
i = 0; y = 0! 
while y < 100000! 
y += square(i)! 
i = i + 1! 
end 
13 
トレース 
BB0: 
guard_method_redefine(Fixnum.*) 
guard_method_redefine(Fixnum.+) 
guard_method_redefine(Fixnum.<) 
BB1: 
guard_is_fixnum(i) 
push_frame 
# 
invoke 
square 
guard_method_redefine(Fixnum.*) 
tmp 
= 
fixnum_mul(i, 
i) 
pop_frame 
# 
leave 
square 
guard_method_redefine(Fixnum.+) 
y 
= 
fixnum_plus(y, 
tmp) 
guard_method_redefine(Fixnum.+) 
i 
= 
fixnum_plus(i, 
1) 
guard_method_redefine(Fixnum.<) 
tmp2 
= 
fixnum_lt(i, 
100000) 
guard_nil(tmp2) 
jump 
BB1 
RuJIT 
can 
hoist 
guard_method_redefine
Op=mize 
trace 
def square(x)! 
return x * x! 
end! 
! 
i = 0; y = 0! 
while y < 100000! 
y += square(i)! 
i = i + 1! 
end 
14 
トレース 
BB0: 
guard_method_redefine(Fixnum.*) 
guard_method_redefine(Fixnum.+) 
guard_method_redefine(Fixnum.<) 
BB1: 
guard_is_fixnum(i) 
push_frame 
guard_method_redefine(Fixnum.*) 
tmp 
= 
fixnum_mul(i, 
i) 
pop_frame 
guard_method_redefine(Fixnum.+) 
y 
= 
fixnum_plus(y, 
tmp) 
guard_method_redefine(Fixnum.+) 
i 
= 
fixnum_plus(i, 
1) 
guard_method_redefine(Fixnum.<) 
tmp2 
= 
fixnum_lt(i, 
100000) 
guard_nil(tmp2) 
jump 
BB1 
RuJIT 
can 
remove 
method 
frame
Op=mize 
trace 
def square(x)! 
return x * x! 
end! 
! 
i = 0; y = 0! 
while y < 100000! 
y += square(i)! 
i = i + 1! 
end 
15 
トレース 
BB0: 
guard_method_redefine(Fixnum.*) 
guard_method_redefine(Fixnum.+) 
guard_method_redefine(Fixnum.<) 
guard_is_fixnum(i) 
BB1: 
guard_is_fixnum(i) 
push_frame 
guard_method_redefine(Fixnum.*) 
tmp 
= 
fixnum_mul(i, 
i) 
pop_frame 
guard_method_redefine(Fixnum.+) 
y 
= 
fixnum_plus(y, 
tmp) 
guard_method_redefine(Fixnum.+) 
i 
= 
fixnum_plus(i, 
1) 
guard_method_redefine(Fixnum.<) 
tmp2 
= 
fixnum_lt(i, 
100000) 
guard_nil(tmp2) 
jump 
BB1 
RuJIT 
can 
hoist 
guard_is_fixnum 
Because 
variable 
‘i’ 
is 
always 
fixnum
Op=mize 
trace 
def square(x)! 
return x * x! 
end! 
! 
i = 0; y = 0! 
while y < 100000! 
y += square(i)! 
i = i + 1! 
end 
16 
Na=ve 
code 
BB0: 
guard_method_redefine(Fixnum.*) 
guard_method_redefine(Fixnum.+) 
guard_method_redefine(Fixnum.<) 
guard_is_fixnum(i) 
BB1: 
tmp 
= 
fixnum_mul(i, 
i) 
y 
= 
fixnum_plus(y, 
tmp) 
i 
= 
fixnum_plus(i, 
1) 
tmp2 
= 
fixnum_lt(i, 
100000) 
guard_nil(tmp2) 
jump 
BB1 
トレース
トレースからインタプリタへの移行 
YARV 
Bytecode 
17 
Fixnum.* 
is 
redefined! 
Invalidate 
compiled 
code 
and 
Fall 
back 
to 
yarv 
interpreter 
#toplevel 
09 
putobject 
100 
11 
send 
:=mes, 
block 
17 
leave 
#block 
02 
putself 
03 
getdynamic 
i 
06 
send 
:puts, 
nil 
14 
leave 
Parser 
AST 
Bytecode 
Compiler 
Interpreter 
CRuby 
BB0: 
guard_method_redefine(Fixnum.*) 
guard_method_redefine(Fixnum.+) 
guard_method_redefine(Fixnum.<) 
guard_is_fixnum(i) 
BB1: 
tmp 
= 
fixnum_mul(i, 
i) 
y 
= 
fixnum_plus(y, 
tmp) 
i 
= 
fixnum_plus(i, 
1) 
tmp2 
= 
fixnum_lt(i, 
100000) 
guard_nil(tmp2) 
jump 
BB1
ここまでのまとめ 
トレース方式JITコンパイラ 
• 特徴 
– 頻繁に実行されるパスのみをコンパイル 
• 実行時に収集した仮定,前提条件を含めてコンパイル 
– 積極的な最適化が可能 
• JITで生成された機械語ではトレースに含まれていない 
パスが実行されるとインタプリタへfall 
back 
• 欠点 
– 頻繁なトレース↔インタプリタ遷移は性能劣化を 
招く 
• スタック,レジスタの書き戻しなど… 
18
RuJITのコンパイル手法 
• YARV 
Bytecode→ 
RuJIT 
IR→ 
C 
code→ 
Na=ve 
code 
– たいていの内部命令はバイトコード命令に対応 
– JIT内部にアセンブラ不要 
• 開発コスト低い 
19 
バイトコード 
命令 
getlocal 
x 
getlocal 
y 
plus 
x, 
y 
Ruby 
Program 
x 
+ 
y 
内部命令 
guard_int 
x 
guard_int 
y 
iadd 
x, 
y 
C言語 
if(is_int(x)){ 
if(is_int(y)){ 
ret 
= 
x 
+ 
y; 
} 
else 
{…} 
} 
else 
{…} 
機械語 
movl 
%edi, 
%ecx 
andl 
%esi, 
%ecx 
xorl 
%eax, 
%eax 
testb 
$1, 
%cl 
je 
LBB0_2 
addl 
%edi, 
%esi 
movl 
%esi, 
%eax 
内部命令に対する 
Cコードテンプレート 
を用いて変換 
gcc 
clang
バイトコードから 
RuJIT内部命令への変換 
• データ変換の記述は煩雑 
– 各バイトコードごとのにスタック操作,pc操作, 
内部データの更新 
– 最適化しやすいように内部命令をどんどん追加 
• 問題:どのように開発コストを抑えつつバグの 
少ない変換を行うか 
→変換規則,内部命令仕様から変換コード自動生成 
• 共通の処理は手で書かない 
20
内部命令記述と生成例 
• 生成例 
• 内部命令の変換則 
21 
define FixnumAdd! 
:def :user! 
(LHS:lir_t, RHS:lir_t)! 
! 
emit FixnumAdd if! 
opcode is opt_plus and! 
method_name is "+" and! 
LHS is Fixnum and! 
RHS is Fixnum! 
! 
if ( // rule0 FixnumAdd! 
(opcode == BIN(opt_plus)) &&! 
(ci->mid == idPLUS) &&! 
(ci->argc == 2) &&! 
(Fixnum.“+”は再定義されていない) &&! 
(FIXNUM_P(params[0])) &&! 
(FIXNUM_P(params[1]))! 
) {! 
Emit_GuardMethod(idPLUS);! 
Emit_GuardTypeFixnum(regs[0]);! 
Emit_GuardTypeFixnum(regs[1]);! 
Emit_FixnumAdd(regs[0], 
regs[1]);! 
}
Op=miza=on 
• 処理/実装コストの低いから,まずは実装 
– Peephole 
Op=miza=on 
– Constant 
Propaga=on 
– Common 
Sub-­‐expression 
Elimina=on 
– Dead 
Code 
Elimina=on 
– Escape 
analysis 
+ 
Stack 
alloca=on 
22
Evalua=on 
• 用いたベンチマーク 
– CRuby処理系付属のベンチマーク(の一部) 
• 比較対象 
– CRuby 
(trunk) 
• 環境 
– OSX 
10.9 
– Clang 
3.5 
23
Evalua=on 
• 多くのベンチマークで2~5倍の高速化 
• いくつかのベンチマークは100倍以上 
24 
10 
9 
8 
7 
6 
5 
4 
3 
2 
1 
0 
〜〜 
〜〜 
〜〜 
〜〜 
〜〜 
〜〜 
〜〜
Evalua=on 
• 変化なし・低速化のケース 
– トレース検出の変更 
– Cで書かれたコードはトレースできない 
Cで定義されているコード 
トレースの検出対応 
できていないケース 
25 
1.2 
1 
0.8 
0.6 
0.4 
0.2 
0 
io_file_create 
io_file_read 
io_file_write 
io_select 
io_select2 
io_select3 
app_factorial 
app_fib
Conclusion 
• RuJIT 
: 
a 
trace 
based 
JIT 
compiler 
for 
CRuby 
– トレース方式JITコンパイラによりRubyスクリプトのうち 
頻繁に実行される箇所を機械語へ変換 
– How 
to 
use 
RuJIT 
1. git 
clone 
git@github.com:imasahiro/rujit.git 
2. cd 
/path/to/rujit 
3. ./configure 
&& 
make 
&& 
make 
install 
4. ruby 
hello_world.rb 
• 今後の課題 
– 互換性(Trace 
API, 
Excep=on, 
Thread対応) 
– Need 
more 
test 
26
FAQ 
• Railsは動く?(もしくは他のrubyプログラムは?) 
– まだ動きません.現在対応中です 
• RuJIT,なんか動きません 
– GithubのIssueに投げてもらえると助かります 
– h~ps://github.com/imasahiro/rujit/issues 
• ◯◯◯との比較は? 
– JRuby, 
Rubinius, 
Topaz, 
mrubyのJIT, 
yarv2llvm, 
CastOff… 
– 現在評価中です 
27

More Related Content

What's hot

SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介MITSUNARI Shigeo
 
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!amusementcreators
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプKohsuke Yuasa
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門Norishige Fukushima
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門natrium11321
 
Boost.Coroutine
Boost.CoroutineBoost.Coroutine
Boost.Coroutinemelpon
 
C++入門?
C++入門?C++入門?
C++入門?tsudaa
 
Shadow gunのサンプルから学べるモバイル最適化
Shadow gunのサンプルから学べるモバイル最適化Shadow gunのサンプルから学べるモバイル最適化
Shadow gunのサンプルから学べるモバイル最適化Katsutoshi Makino
 
Cvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 halfCvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 halftomoaki0705
 
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013Ryo Sakamoto
 
マーク&スイープ勉強会
マーク&スイープ勉強会マーク&スイープ勉強会
マーク&スイープ勉強会7shi
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
 
Popcntによるハミング距離計算
Popcntによるハミング距離計算Popcntによるハミング距離計算
Popcntによるハミング距離計算Norishige Fukushima
 
新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案yohhoy
 
Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介MITSUNARI Shigeo
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.ContextAkira Takahashi
 

What's hot (20)

SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介
 
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプ
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
 
Boost.Coroutine
Boost.CoroutineBoost.Coroutine
Boost.Coroutine
 
llvm入門
llvm入門llvm入門
llvm入門
 
C++入門?
C++入門?C++入門?
C++入門?
 
Shadow gunのサンプルから学べるモバイル最適化
Shadow gunのサンプルから学べるモバイル最適化Shadow gunのサンプルから学べるモバイル最適化
Shadow gunのサンプルから学べるモバイル最適化
 
Cvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 halfCvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 half
 
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
 
マーク&スイープ勉強会
マーク&スイープ勉強会マーク&スイープ勉強会
マーク&スイープ勉強会
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
Popcntによるハミング距離計算
Popcntによるハミング距離計算Popcntによるハミング距離計算
Popcntによるハミング距離計算
 
新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案
 
フラグを愛でる
フラグを愛でるフラグを愛でる
フラグを愛でる
 
Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
 
Emcjp item33,34
Emcjp item33,34Emcjp item33,34
Emcjp item33,34
 

Similar to RubyKaigi2014: Just in Time compiler for CRuby

Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようCookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようKoichi Sasada
 
Or seminar2011final
Or seminar2011finalOr seminar2011final
Or seminar2011finalMikio Kubo
 
Cython intro prelerease
Cython intro prelereaseCython intro prelerease
Cython intro prelereaseShiqiao Du
 
Php in ruby
Php in rubyPhp in ruby
Php in rubydo_aki
 
8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティングTakeshi Takaishi
 
ただのリンカを書いた話.pdf
ただのリンカを書いた話.pdfただのリンカを書いた話.pdf
ただのリンカを書いた話.pdfsimotin13 Miyazaki
 
NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門Shiqiao Du
 
もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…Yasumasa Suenaga
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門伸男 伊藤
 
How to use animation packages in R(Japanese)
How to use animation packages in R(Japanese)How to use animation packages in R(Japanese)
How to use animation packages in R(Japanese)sleipnir002
 
130710 02
130710 02130710 02
130710 02openrtm
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチMasami Ichikawa
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23Masashi Shibata
 
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519Yasuhiro Ishii
 

Similar to RubyKaigi2014: Just in Time compiler for CRuby (20)

Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようCookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
 
Or seminar2011final
Or seminar2011finalOr seminar2011final
Or seminar2011final
 
Cython intro prelerease
Cython intro prelereaseCython intro prelerease
Cython intro prelerease
 
Php in ruby
Php in rubyPhp in ruby
Php in ruby
 
Rの高速化
Rの高速化Rの高速化
Rの高速化
 
8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング
 
ただのリンカを書いた話.pdf
ただのリンカを書いた話.pdfただのリンカを書いた話.pdf
ただのリンカを書いた話.pdf
 
NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門NumPyが物足りない人へのCython入門
NumPyが物足りない人へのCython入門
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 
Gurobi python
Gurobi pythonGurobi python
Gurobi python
 
もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門
 
How to use animation packages in R(Japanese)
How to use animation packages in R(Japanese)How to use animation packages in R(Japanese)
How to use animation packages in R(Japanese)
 
130710 02
130710 02130710 02
130710 02
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチ
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
サイバーエージェントにおけるMLOpsに関する取り組み at PyDataTokyo 23
 
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
 
LLVM最適化のこつ
LLVM最適化のこつLLVM最適化のこつ
LLVM最適化のこつ
 

Recently uploaded

SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 

Recently uploaded (9)

SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 

RubyKaigi2014: Just in Time compiler for CRuby

  • 1. A Just In Time Compiler for CRuby CRuby言語処理系向けJITコンパイラ Masahiro Ide Yokohama Na=onal University RubyKaigi 2014 2014年9月19日(金) 1
  • 2. Outline • Ruby • Just-­‐In-­‐Time(JIT) compiler • RuJIT: a JIT compiler for Ruby ※あまり実装よりの内容ではありません また,CRubyの実装に詳しくない人でも分かる 内容(にしたつもり)です. 2
  • 3. Ruby Language and Implementa=on • Ruby is a dynamically typed scrip=ng language – Support excep=on, garbage collec=on, con=nua=on – CRuby is Ruby interpreter in C (de facto standard implementa=on of Ruby) – Many Implementa=ons JRuby(Java), IRonRuby(.NET), Rubinius(Ruby), MRuby(C), Topaz(PyPy) – Numeric benchmarks 10-­‐100 =mes slower than C • Need to improve!!! 3
  • 4. CRuby Internal YARV bytecode #toplevel 09 putobject 100 11 send :=mes, block 17 leave #block 02 putself 03 getdynamic i 06 send :puts, nil 14 leave Ruby code 100.=mes do |i| puts i end Parser AST Bytecode Compiler Interpreter Memory Manager C library CPU 4
  • 5. HOW TO SPEEDUP RUBY 1. Translate/Compile to low-­‐level language – プログラム実行中にコンパイル→ Just-­‐In-­‐Time(JIT) – プログラム実行前にコンパイル→Ahead-­‐Of-­‐Time(AOT) – Target • Java bytecode (JRuby), .NET CLR (IronRuby), LLVM IR(Rubinius) 2. Speedup Interpreter – ディスパッチ方法の工夫 – メソッドキャッシュ – … 5
  • 6. Outline • Ruby • Just-­‐In-­‐Time(JIT) compiler • RuJIT: a JIT compiler for Ruby – Design – Usage – Current status 6
  • 7. RuJIT • A Trace based JIT compiler for CRuby – Like Firefox’s javascript VM approach • Based on current version of CRuby • Started in April 2014 • More Speed, Speed, Speed – … but maintain compa=bility with current Ruby 7
  • 8. Implementa=on Strategies • Objec=ve – Improve Ruby’s performance • Development policy – Low development cost • 1 person, 2~3 month – High extensibility • Easy to develop new op=miza=on techniques – 実用的なソフトウェア • いつかRubyのメインラインに →この方針に基づいて設計を行っている 8
  • 9. RuJIT overview RuJIT YARV bytecode #toplevel 09 putobject 100 11 send :=mes, block 17 leave #block 02 putself 03 getdynamic i 06 send :puts, nil 14 leave Ruby code 100.=mes do |i| puts i end Parser AST Bytecode Compiler Interpreter Memory Manager C library CPU Na=ve code 9
  • 10. RuJIT Design • Trace based JIT compiler – Detect hot path(e.g. loop) • Intermediate Representa=on (IR) for op=miza=on – Low level – Contain run=me informa=on • Na=ve Code translator – Use C compiler (GCC, clang) as backend 10 YARV Trace Selec=on Engine Trace Cache RuJIT Run=me CRuby Run=me IR Generator Op=mizer invoke Code Generator C Compiler Na=ve code Trace compile
  • 11. トレース方式コンパイラの実行の流れ 11 def square(x)! return x * x! end! ! i = 0; y = 0! while y < 100000! y += square(i)! i = i + 1! end
  • 12. Construct trace def square(x)! return x * x! end! ! i = 0; y = 0! while y < 100000! y += square(i)! i = i + 1! end 12 BB0: guard_method_redefine(Fixnum.*) guard_method_redefine(Fixnum.+) guard_method_redefine(Fixnum.<) BB1: guard_is_fixnum(i) push_frame # invoke square guard_method_redefine(Fixnum.*) tmp = fixnum_mul(i, i) pop_frame # leave square guard_method_redefine(Fixnum.+) y = fixnum_plus(y, tmp) guard_method_redefine(Fixnum.+) i = fixnum_plus(i, 1) guard_method_redefine(Fixnum.<) tmp2 = fixnum_lt(i, 100000) guard_nil(tmp2) jump BB1 トレース
  • 13. Op=mize trace def square(x)! return x * x! end! ! i = 0; y = 0! while y < 100000! y += square(i)! i = i + 1! end 13 トレース BB0: guard_method_redefine(Fixnum.*) guard_method_redefine(Fixnum.+) guard_method_redefine(Fixnum.<) BB1: guard_is_fixnum(i) push_frame # invoke square guard_method_redefine(Fixnum.*) tmp = fixnum_mul(i, i) pop_frame # leave square guard_method_redefine(Fixnum.+) y = fixnum_plus(y, tmp) guard_method_redefine(Fixnum.+) i = fixnum_plus(i, 1) guard_method_redefine(Fixnum.<) tmp2 = fixnum_lt(i, 100000) guard_nil(tmp2) jump BB1 RuJIT can hoist guard_method_redefine
  • 14. Op=mize trace def square(x)! return x * x! end! ! i = 0; y = 0! while y < 100000! y += square(i)! i = i + 1! end 14 トレース BB0: guard_method_redefine(Fixnum.*) guard_method_redefine(Fixnum.+) guard_method_redefine(Fixnum.<) BB1: guard_is_fixnum(i) push_frame guard_method_redefine(Fixnum.*) tmp = fixnum_mul(i, i) pop_frame guard_method_redefine(Fixnum.+) y = fixnum_plus(y, tmp) guard_method_redefine(Fixnum.+) i = fixnum_plus(i, 1) guard_method_redefine(Fixnum.<) tmp2 = fixnum_lt(i, 100000) guard_nil(tmp2) jump BB1 RuJIT can remove method frame
  • 15. Op=mize trace def square(x)! return x * x! end! ! i = 0; y = 0! while y < 100000! y += square(i)! i = i + 1! end 15 トレース BB0: guard_method_redefine(Fixnum.*) guard_method_redefine(Fixnum.+) guard_method_redefine(Fixnum.<) guard_is_fixnum(i) BB1: guard_is_fixnum(i) push_frame guard_method_redefine(Fixnum.*) tmp = fixnum_mul(i, i) pop_frame guard_method_redefine(Fixnum.+) y = fixnum_plus(y, tmp) guard_method_redefine(Fixnum.+) i = fixnum_plus(i, 1) guard_method_redefine(Fixnum.<) tmp2 = fixnum_lt(i, 100000) guard_nil(tmp2) jump BB1 RuJIT can hoist guard_is_fixnum Because variable ‘i’ is always fixnum
  • 16. Op=mize trace def square(x)! return x * x! end! ! i = 0; y = 0! while y < 100000! y += square(i)! i = i + 1! end 16 Na=ve code BB0: guard_method_redefine(Fixnum.*) guard_method_redefine(Fixnum.+) guard_method_redefine(Fixnum.<) guard_is_fixnum(i) BB1: tmp = fixnum_mul(i, i) y = fixnum_plus(y, tmp) i = fixnum_plus(i, 1) tmp2 = fixnum_lt(i, 100000) guard_nil(tmp2) jump BB1 トレース
  • 17. トレースからインタプリタへの移行 YARV Bytecode 17 Fixnum.* is redefined! Invalidate compiled code and Fall back to yarv interpreter #toplevel 09 putobject 100 11 send :=mes, block 17 leave #block 02 putself 03 getdynamic i 06 send :puts, nil 14 leave Parser AST Bytecode Compiler Interpreter CRuby BB0: guard_method_redefine(Fixnum.*) guard_method_redefine(Fixnum.+) guard_method_redefine(Fixnum.<) guard_is_fixnum(i) BB1: tmp = fixnum_mul(i, i) y = fixnum_plus(y, tmp) i = fixnum_plus(i, 1) tmp2 = fixnum_lt(i, 100000) guard_nil(tmp2) jump BB1
  • 18. ここまでのまとめ トレース方式JITコンパイラ • 特徴 – 頻繁に実行されるパスのみをコンパイル • 実行時に収集した仮定,前提条件を含めてコンパイル – 積極的な最適化が可能 • JITで生成された機械語ではトレースに含まれていない パスが実行されるとインタプリタへfall back • 欠点 – 頻繁なトレース↔インタプリタ遷移は性能劣化を 招く • スタック,レジスタの書き戻しなど… 18
  • 19. RuJITのコンパイル手法 • YARV Bytecode→ RuJIT IR→ C code→ Na=ve code – たいていの内部命令はバイトコード命令に対応 – JIT内部にアセンブラ不要 • 開発コスト低い 19 バイトコード 命令 getlocal x getlocal y plus x, y Ruby Program x + y 内部命令 guard_int x guard_int y iadd x, y C言語 if(is_int(x)){ if(is_int(y)){ ret = x + y; } else {…} } else {…} 機械語 movl %edi, %ecx andl %esi, %ecx xorl %eax, %eax testb $1, %cl je LBB0_2 addl %edi, %esi movl %esi, %eax 内部命令に対する Cコードテンプレート を用いて変換 gcc clang
  • 20. バイトコードから RuJIT内部命令への変換 • データ変換の記述は煩雑 – 各バイトコードごとのにスタック操作,pc操作, 内部データの更新 – 最適化しやすいように内部命令をどんどん追加 • 問題:どのように開発コストを抑えつつバグの 少ない変換を行うか →変換規則,内部命令仕様から変換コード自動生成 • 共通の処理は手で書かない 20
  • 21. 内部命令記述と生成例 • 生成例 • 内部命令の変換則 21 define FixnumAdd! :def :user! (LHS:lir_t, RHS:lir_t)! ! emit FixnumAdd if! opcode is opt_plus and! method_name is "+" and! LHS is Fixnum and! RHS is Fixnum! ! if ( // rule0 FixnumAdd! (opcode == BIN(opt_plus)) &&! (ci->mid == idPLUS) &&! (ci->argc == 2) &&! (Fixnum.“+”は再定義されていない) &&! (FIXNUM_P(params[0])) &&! (FIXNUM_P(params[1]))! ) {! Emit_GuardMethod(idPLUS);! Emit_GuardTypeFixnum(regs[0]);! Emit_GuardTypeFixnum(regs[1]);! Emit_FixnumAdd(regs[0], regs[1]);! }
  • 22. Op=miza=on • 処理/実装コストの低いから,まずは実装 – Peephole Op=miza=on – Constant Propaga=on – Common Sub-­‐expression Elimina=on – Dead Code Elimina=on – Escape analysis + Stack alloca=on 22
  • 23. Evalua=on • 用いたベンチマーク – CRuby処理系付属のベンチマーク(の一部) • 比較対象 – CRuby (trunk) • 環境 – OSX 10.9 – Clang 3.5 23
  • 24. Evalua=on • 多くのベンチマークで2~5倍の高速化 • いくつかのベンチマークは100倍以上 24 10 9 8 7 6 5 4 3 2 1 0 〜〜 〜〜 〜〜 〜〜 〜〜 〜〜 〜〜
  • 25. Evalua=on • 変化なし・低速化のケース – トレース検出の変更 – Cで書かれたコードはトレースできない Cで定義されているコード トレースの検出対応 できていないケース 25 1.2 1 0.8 0.6 0.4 0.2 0 io_file_create io_file_read io_file_write io_select io_select2 io_select3 app_factorial app_fib
  • 26. Conclusion • RuJIT : a trace based JIT compiler for CRuby – トレース方式JITコンパイラによりRubyスクリプトのうち 頻繁に実行される箇所を機械語へ変換 – How to use RuJIT 1. git clone git@github.com:imasahiro/rujit.git 2. cd /path/to/rujit 3. ./configure && make && make install 4. ruby hello_world.rb • 今後の課題 – 互換性(Trace API, Excep=on, Thread対応) – Need more test 26
  • 27. FAQ • Railsは動く?(もしくは他のrubyプログラムは?) – まだ動きません.現在対応中です • RuJIT,なんか動きません – GithubのIssueに投げてもらえると助かります – h~ps://github.com/imasahiro/rujit/issues • ◯◯◯との比較は? – JRuby, Rubinius, Topaz, mrubyのJIT, yarv2llvm, CastOff… – 現在評価中です 27