Slide 1

Slide 1 text

T R E A S U R E D A T A The Method JIT Compiler for Ruby 2.6 Takashi Kokubun / @k0kubun RubyKaigi 2018

Slide 2

Slide 2 text

T R E A S U R E D A T A Maintainer of ERB, Haml Developing JIT compiler for Ruby 2.6 @k0kubun

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

• 2017 Sep: LLVM JIT (EN) • 2017 Nov: YARV MJIT (EN) • 2017 Dec: YARV MJIT (JA) • 2018 Feb: ERB generation (JA) • 2018 Apr: Preview2 optimizations (EN) .ZQBTUUBMLTBCPVU3VCZT+*5 https://speakerdeck.com/k0kubun

Slide 5

Slide 5 text

1. Current Status 2. JIT on Rails 3. Dive Into Native Code 4. Method Inlining 5PEBZTUBML

Slide 6

Slide 6 text

1. CURRENT STATUS

Slide 7

Slide 7 text

• JIT in 2.6.0-preview2 is not production ready yet • Fixing bugs by a race condition • I'll introduce current status of: • Implementation • Portability • Performance $VSSFOUTUBUVT

Slide 8

Slide 8 text

IMPLEMENTATION

Slide 9

Slide 9 text

.+*53VCZ`T+*5BSDIJUFDUVSF Ruby Process Disk Memory MJIT worker Thread Method #1 Bytecode Ruby VM Thread Interpret

Slide 10

Slide 10 text

.+*53VCZ`T+*5BSDIJUFDUVSF Ruby Process Disk Memory MJIT worker Thread Method #1 Bytecode Ruby VM Thread Interpret Request JIT-ing #1

Slide 11

Slide 11 text

.+*53VCZ`T+*5BSDIJUFDUVSF Ruby Process Disk Memory Method #1 Bytecode Ruby VM Thread Interpret Request JIT-ing #1 Method #1 C code MJIT worker Thread Generate

Slide 12

Slide 12 text

.+*53VCZ`T+*5BSDIJUFDUVSF Ruby Process Disk Memory Method #1 Bytecode Ruby VM Thread Interpret Request JIT-ing #1 Method #1 C code MJIT worker Thread Generate Method #1 SO file Run C compiler

Slide 13

Slide 13 text

.+*53VCZ`T+*5BSDIJUFDUVSF Ruby Process Disk Memory Method #1 Bytecode Ruby VM Thread Interpret Request JIT-ing #1 Method #1 C code MJIT worker Thread Generate Method #1 SO file Run C compiler Method #1 Native code Load

Slide 14

Slide 14 text

.+*53VCZ`T+*5BSDIJUFDUVSF Ruby Process Disk Memory Method #1 Bytecode Interpret Request JIT-ing #1 Method #1 C code MJIT worker Thread Generate Method #1 SO file Run C compiler Method #1 Native code Load Ruby VM Thread Call

Slide 15

Slide 15 text

)PXJTUIJTJNQMFNFOUFE Ruby Process Disk Memory Method #1 Bytecode Interpret Request JIT-ing #1 Method #1 C code MJIT worker Thread Generate Method #1 SO file Run C compiler Method #1 Native code Load Ruby VM Thread Call

Slide 16

Slide 16 text

)PXJTUIJTJNQMFNFOUFE Ruby Code def three 1 + 2 end Bytecode putobject 1 putobject 2 opt_plus leave =

Slide 17

Slide 17 text

)PXJTUIJTJNQMFNFOUFE Ruby Code def three 1 + 2 end Bytecode putobject 1 putobject 2 opt_plus leave = C code three() { VALUE stack[2]; /* putobject 1 */ stack[0] = 1; }

Slide 18

Slide 18 text

)PXJTUIJTJNQMFNFOUFE Ruby Code def three 1 + 2 end Bytecode putobject 1 putobject 2 opt_plus leave = C code three() { VALUE stack[2]; /* putobject 1 */ stack[0] = 1; /* putobject 2 */ stack[1] = 2; }

Slide 19

Slide 19 text

)PXJTUIJTJNQMFNFOUFE Ruby Code def three 1 + 2 end Bytecode putobject 1 putobject 2 opt_plus leave = C code three() { VALUE stack[2]; /* putobject 1 */ stack[0] = 1; /* putobject 2 */ stack[1] = 2; /* opt_plus */ stack[0] = opt_plus( stack[0], stack[1] ); }

Slide 20

Slide 20 text

)PXJTUIJTJNQMFNFOUFE Ruby Code def three 1 + 2 end Bytecode putobject 1 putobject 2 opt_plus leave = C code three() { VALUE stack[2]; /* putobject 1 */ stack[0] = 1; /* putobject 2 */ stack[1] = 2; /* opt_plus */ stack[0] = opt_plus( stack[0], stack[1] ); /* leave */ return stack[0]; }

Slide 21

Slide 21 text

$DPEFHFOFSBUPS ERB template: mjit_compile.inc.erb

Slide 22

Slide 22 text

$DPEFHFOFSBUPS ERB template: mjit_compile.inc.erb VM instructions: insns.def

Slide 23

Slide 23 text

$DPEFHFOFSBUPS ERB template: mjit_compile.inc.erb VM instructions: insns.def C code generator: mjit_compile.inc Render Copy definition

Slide 24

Slide 24 text

• Based on Ruby 2.5’s Ruby VM • If JIT is disabled, everything must work in 2.6 • JIT implementation is automatically generated • To keep up with frequent Ruby VM changes 3VCZT+*5EFTJHO

Slide 25

Slide 25 text

PORTABILITY

Slide 26

Slide 26 text

$DPNQJMFSTVQQPSUT GCC Clang Visual C++ Intel C++ Compiler MJIT worker ○ ○ ○ ○ JIT header ○ ○ × ○ CLI support ○ ○ ○ × Support plan Done Done Next Later Now MJIT worker (native thread, dynamic loading) runs on Windows and UNIX

Slide 27

Slide 27 text

1MBUGPSNTVQQPSUTXJUI($$ Linux MinGW Solaris NetBSD FreeBSD JIT header ○ ˚ ○ ○ ○ test_jit.rb ○ ○ ○ ? × MinGW header is not minimized and thus compilation speed is slow. I guess NetBSD works but we don’t have NetBSD RubyCI. GCC on FreeBSD is crashing.

Slide 28

Slide 28 text

1MBUGPSNTVQQPSUTXJUI$MBOH Linux macOS OpenBSD JIT header ○ ○ ○ test_jit.rb ○ ○ ? I guess OpenBSD works but we don’t have OpenBSD RubyCI

Slide 29

Slide 29 text

PERFORMANCE

Slide 30

Slide 30 text

3VCZ,BJHJ-5--7.+*5

Slide 31

Slide 31 text

3VCZ,BJHJ-5--7.+*5

Slide 32

Slide 32 text

3VCZ,BJHJ 5IJTUBML https://benchmark-driver.github.io/benchmarks/mjit/commits.html

Slide 33

Slide 33 text

3VCZ,BJHJ 5IJTUBML https://benchmark-driver.github.io/benchmarks/mjit/commits.html 2.6.0 Preview1 2.6.0 Preview2 5.7x faster

Slide 34

Slide 34 text

0QUDBSSPU GQT Ruby 2.0 trunk trunk+JIT 1.49x → 2.03x https://gist.github.com/k0kubun/95c81358af6f34b4d0a71425da871178

Slide 35

Slide 35 text

3BJMT %JTDPVSTF

Slide 36

Slide 36 text

3BJMT %JTDPVSTF

Slide 37

Slide 37 text

2. JIT ON RAILS

Slide 38

Slide 38 text

• Generated code should be faster in general • What's different from Optcarrot? 8IZ3BJMTCFDPNFTTMPXXJUI+*5

Slide 39

Slide 39 text

1. longjmp by exception is slow 2. Profiling method calls has overhead 3. JIT-ed call is canceled too often 4. JIT compilation has overhead 5. Calling JIT-ed code has overhead .ZIZQPUIFTJT

Slide 40

Slide 40 text

• When a method is returned from its child block, it calls longjmp(3) • VM is implemented with just return statement and may be faster in that case MPOHKNQCZFYDFQUJPOJTTMPX

Slide 41

Slide 41 text

-FUTDIFDLJGMPOHKNQJTDBMMFE • Fortunately, longjmp was not used in this Discourse endpoint

Slide 42

Slide 42 text

• MJIT counts method calls to decide which method to compile with JIT enabled • This was suspected in [Bug #14490] 1SPGJMJOHNFUIPEDBMMTIBTPWFSIFBE

Slide 43

Slide 43 text

-FUTDPVOUJUFWFOJG+*5JTEJTBCMFE

Slide 44

Slide 44 text

/PCJHEJGGFSFODFCZQSPGJMJOHNFUIPEDBMMT trunk No options modified No options trunk --jit JIT × × ○ Profiling × ○ ○ Percentile: ms GET /: 50: 58.4ms 75: 65.4ms 90: 67.9ms 99: 131.1ms GET /: 50: 58.5ms 75: 64.6ms 90: 67.8ms 99: 127.3ms GET /: 50: 66.3ms 75: 72.3ms 90: 77.0ms 99: 133.3ms `ruby script/simple_bench.rb 1000` with: https://github.com/k0kubun/discourse/tree/20fc03558f16aff94c6c017347783374cf4a0ca8

Slide 45

Slide 45 text

• MJIT has a kind of de-optimization to fallback to VM interpretation when any assumption is not met • ex) Method redefinition, etc. • Such fallback might be an overhead +*5FEDBMMJTDBODFMMFEUPPPGUFO

Slide 46

Slide 46 text

-FUTMPHBMM+*5DBODFMMBUJPO

Slide 47

Slide 47 text

5IFSBUJPPG+*5DBODFMMBUJPO JIT-ed calls Cancel by opt_xxx Cancel by call cache Optcarrot 49,171,765 786,842 (1.60%) 0 (0.00%) Discourse 1,000 requests 168,925,050 19,394,792 (11.5%) 10,092,254 (5.97%) JIT cancel reasons: • opt_xxx: Non-core class is given to +, -, *, /, #[], etc. • call cache: Method redefinition, receiver class is changed

Slide 48

Slide 48 text

8IZ+*5DBODFMIBQQFOTTPPGUFO • Current JIT doesn't discard any JIT-ed code whose assumption is not met • opt_xxx is performing badly when a receiver is not a core class like Integer, Float, String, Array, Hash

Slide 49

Slide 49 text

8IZ+*5DBODFMIBQQFOTTPPGUFO • Current JIT doesn't discard any JIT-ed code whose assumption is not met • opt_xxx is performing badly when a receiver is not a core class like Integer, Float, String, Array, Hash There are many #[] for non Hash/Array classes in Rails

Slide 50

Slide 50 text

*GJYFEUIJTJTTVFGPS<> S

Slide 51

Slide 51 text

PQU@YYYDBODFMJTEFDSFBTFENVDI JIT-ed calls Cancel by opt_xxx Cancel by call cache Discourse Before 168,925,050 19,394,792 (11.5%) 10,092,254 (5.97%) Discourse After 75,150,482 2,849,825 (3.79%) 3,072,673 (4.09%) #[] has a major impact on Rails. Others are to be improved...

Slide 52

Slide 52 text

• Appending a method to JIT-ed queue may have overhead • GCC or Clang may use the same CPU core, or it may cost to transfer data to another core +*5DPNQJMBUJPOIBTPWFSIFBE

Slide 53

Slide 53 text

1SFQBSF3VCZ7..+*5TUPQBOE Stop JIT compilation

Slide 54

Slide 54 text

+*5FOBCMFEWT+*5TUPQQFE JIT enabled 1000 requests JIT enabled 1000 requests JIT stopped 1000 requests RubyVM::MJIT.stop Measure

Slide 55

Slide 55 text

+*5DPNQJMBUJPOIBEPWFSIFBE No options --jit → Stop --jit Code is JIT-ed × ○ ○ JIT is going on × × ○ Percentile: ms GET /: 50: 60.4ms 75: 66.9ms 90: 69.6ms 99: 125.4ms GET /: 50: 65.1ms 75: 72.4ms 90: 75.8ms 99: 145.6ms GET /: 50: 68.4ms 75: 74.8ms 90: 80.0ms 99: 137.2ms But this overhead is excluded from [Bug #14490] degradation…

Slide 56

Slide 56 text

• JIT-ed code behaves slower only on an exception or JIT cancellation, but they weren’t culprit • JIT compilation does not dominate the slowness • Then, calling native code has overhead…? $BMMJOH+*5FEDPEFIBTPWFSIFBE

Slide 57

Slide 57 text

-FU`TDIFDL+*5FEDBMMPWFSIFBE

Slide 58

Slide 58 text

-FU`TDIFDL+*5FEDBMMPWFSIFBE

Slide 59

Slide 59 text

$BMMJOH+*5FEDPEFXBTTMPX JIT disabled JIT enabled Duration 2.17s 2.45s

Slide 60

Slide 60 text

-FU`TQSPGJMFXJUIQFSG

Slide 61

Slide 61 text

(VBSEGPSKJUXBJUUBLFTUJNF

Slide 62

Slide 62 text

4LJQKJUXBJUDIFDLJONBJOCSBODI r63480

Slide 63

Slide 63 text

*NQSPWFEBMJUUMF JIT disabled JIT enabled Duration 2.17s 2.31s (-0.14s)

Slide 64

Slide 64 text

3FNBJOJOHTXBTGPS Additional memory access here …But it wasn’t a big deal in Rails

Slide 65

Slide 65 text

8IBUJGUIFSFBSFBMPUPGNFUIPET

Slide 66

Slide 66 text

$BMMJOHNBOZEJGGFSFOUNFUIPETJTTMPX Called methods 1 method 15 methods JIT disabled 3.69s 3.71s JIT enabled 3.79s 5.34s Duration with the same total calls

Slide 67

Slide 67 text

$BMMJOHNBOZEJGGFSFOUNFUIPETJTTMPX 0 1.5 3 4.5 6 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 VM JIT

Slide 68

Slide 68 text

$BMMJOHNBOZEJGGFSFOUNFUIPETJTTMPX 0 1.5 3 4.5 6 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 VM JIT 6 12 19

Slide 69

Slide 69 text

)PUNFUIPETPG0QUDBSSPU Top 6 methods dominate 50%

Slide 70

Slide 70 text

)PUNFUIPETPG%JTDPVSTF Top 6 methods are only 18% They are not so hot.

Slide 71

Slide 71 text

8IZEPFTUIJTIBQQFO 0 1.5 3 4.5 6 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 VM JIT 6 12 19

Slide 72

Slide 72 text

-FU`TTFFlQFSGTUBUz 6 methods 40 methods

Slide 73

Slide 73 text

lJOTOQFSDZDMFzJTWFSZEJGGFSFOU 6 methods 40 methods

Slide 74

Slide 74 text

YDZDMFTGPSBMNPTUUIFTBNFJOTOT 6 methods 40 methods

Slide 75

Slide 75 text

6 methods

Slide 76

Slide 76 text

40 methods

Slide 77

Slide 77 text

&BDINFUIPE TPGJMF JTVTJOHPOFQBHF .#

Slide 78

Slide 78 text

40 methods w/ the same so file PoC

Slide 79

Slide 79 text

• Ongoing JIT compilation may have overhead • JIT cancel is happening frequently (to be fixed) • It stalls to load many different methods (to be fixed) 3FBTPOPG3BJMTTMPXEPXOPO+*5

Slide 80

Slide 80 text

3. DIVE INTO NATIVE CODE

Slide 81

Slide 81 text

&YBNQMF Ruby Code def three 1 + 2 end Bytecode putobject 1 putobject 2 opt_plus leave =

Slide 82

Slide 82 text

&YBNQMF Ruby Code def three 1 + 2 end Bytecode putobject 1 putobject 2 opt_plus leave = C code three() { VALUE stack[2]; /* putobject 1 */ stack[0] = 1; /* putobject 2 */ stack[1] = 2; /* opt_plus */ stack[0] = opt_plus( stack[0], stack[1] ); /* leave */ return stack[0]; }

Slide 83

Slide 83 text

More detailed definition before inlining opt_plus

Slide 84

Slide 84 text

opt_plus inlined

Slide 85

Slide 85 text

Native code generated by GCC (output of perf)

Slide 86

Slide 86 text

Integer#+ redefinition check

Slide 87

Slide 87 text

JIT cancel handler Let's ignore this Integer#+ redefinition check

Slide 88

Slide 88 text

Integer#+ redefinition check

Slide 89

Slide 89 text

SET_SP: VM's behavior which can be removed Integer#+ redefinition check

Slide 90

Slide 90 text

Check interrupts like SIGINT, another thread Interruption handler Integer#+ redefinition check SET_SP: VM's behavior which can be removed

Slide 91

Slide 91 text

Interruption handler Check interrupts like SIGINT, another thread Pop VM call frame Integer#+ redefinition check SET_SP: VM's behavior which can be removed

Slide 92

Slide 92 text

Pop VM call frame Interruption handler Check interrupts like SIGINT, another thread Return 3 FIX2INT(0x7) == 3 Integer#+ redefinition check SET_SP: VM's behavior which can be removed

Slide 93

Slide 93 text

So what?

Slide 94

Slide 94 text

Instruction dispatch Instruction dispatch Instruction dispatch Instruction dispatch 1. Instruction dispatch cost is removed

Slide 95

Slide 95 text

Program counter motion Program counter motion Program counter motion Program counter motion 2. No program counter motion

Slide 96

Slide 96 text

Stack pointer motion Stack pointer motion Stack pointer motion Forgot to remove this 3. Stack pointer motion is reduced

Slide 97

Slide 97 text

And also...

Slide 98

Slide 98 text

4. This optimization is delegated to GCC

Slide 99

Slide 99 text

8IBUJGJUTNPSFDPNQMFY def six 4 + 8 - 3 * 4 / 2 end

Slide 100

Slide 100 text

No content

Slide 101

Slide 101 text

Fixnum#+ redefinition check Fixnum#* redefinition check Fixnum#/ redefinition check Fixnum#- redefinition check Return 6 FIX2INT(0xd) == 6

Slide 102

Slide 102 text

-BTU&YBNQMFXIJMFMPPQ def while_loop i = 0 while i < 1000000 i += 1 end end i = 0 while i < 2000 while_loop i += 1 end

Slide 103

Slide 103 text

-BTU&YBNQMFXIJMFMPPQ VM: 22.9s JIT: 2.8s Why it becomes so faster? 8.18x faster

Slide 104

Slide 104 text

-FUTTFFUIFOBUJWFDPEFPGXIJMF@MPPQ i = 0 while i < 1000000 i += 1 end

Slide 105

Slide 105 text

No content

Slide 106

Slide 106 text

j They are JIT cancel handlers Let's ignore them

Slide 107

Slide 107 text

No content

Slide 108

Slide 108 text

They are interruption handlers Let's ignore them

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

They are write-barrier-related slow paths Let's ignore them

Slide 111

Slide 111 text

No content

Slide 112

Slide 112 text

It is Bignum promotion handler Let's ignore them

Slide 113

Slide 113 text

No content

Slide 114

Slide 114 text

No content

Slide 115

Slide 115 text

"HBJO MFUTTFFUIFOBUJWFDPEFPG i = 0 while i < 1000000 i += 1 end

Slide 116

Slide 116 text

c i = 0

Slide 117

Slide 117 text

i = 0 check interrupts c

Slide 118

Slide 118 text

i = 0 c Fixnum?(i) for #< check interrupts

Slide 119

Slide 119 text

i = 0 c check interrupts Fixnum#< redefined? Fixnum?(i) for #<

Slide 120

Slide 120 text

i = 0 c check interrupts i < 1000000 Fixnum?(i) for #< Fixnum#< redefined?

Slide 121

Slide 121 text

i = 0 c i < 1000000 check interrupts check interrupts Fixnum?(i) for #< Fixnum#< redefined?

Slide 122

Slide 122 text

i = 0 c i < 1000000 check interrupts check interrupts Fixnum#+ redefined? Fixnum?(i) for #< Fixnum#< redefined?

Slide 123

Slide 123 text

i = 0 c i < 1000000 check interrupts check interrupts i + 1 Fixnum?(i) for #< Fixnum#< redefined? Fixnum#+ redefined?

Slide 124

Slide 124 text

i = 0 c i < 1000000 check interrupts check interrupts Int overflow? i + 1 Fixnum?(i) for #< Fixnum#< redefined? Fixnum#+ redefined?

Slide 125

Slide 125 text

i = 0 c i < 1000000 check interrupts check interrupts Int overflow? can't optimize #+ ? i + 1 Fixnum?(i) for #< Fixnum#< redefined? Fixnum#+ redefined?

Slide 126

Slide 126 text

i = 0 c i < 1000000 check interrupts check interrupts Int overflow? can't optimize #+ ? i + 1 Fixnum?(i) for #< Fixnum#< redefined? Fixnum#+ redefined? set i for VM + check WB

Slide 127

Slide 127 text

i = 0 c i < 1000000 check interrupts check interrupts Int overflow? can't optimize #+ ? i + 1 Fixnum?(i) for #< Fixnum#< redefined? Fixnum#+ redefined? set i for VM + check WB set i for JIT

Slide 128

Slide 128 text

i = 0 c i < 1000000 check interrupts check interrupts Int overflow? i + 1 Fixnum?(i) for #< Fixnum#< redefined? Fixnum#+ redefined? can't optimize #+ ? set i for VM + check WB set i for JIT

Slide 129

Slide 129 text

• #+ and #< are performed on not VM stack but registers • #+ and #< share some instructions to check redefinition • Unnecessary type checks are omitted from the loop 8IZXIJMFMPPQCFDPNFTGBTUFS

Slide 130

Slide 130 text

4. METHOD INLINING

Slide 131

Slide 131 text

• Many optimizations are possible because C compiler can know definitions • If we could inline methods, C compiler would be able to optimize more -FU$DPNQJMFSXPSLIBSE

Slide 132

Slide 132 text

1. x 2. x 3. x 8IFOJTNFUIPEJOMJOJOHQPTTJCMF

Slide 133

Slide 133 text

1. JIT compiler can know definitions 2. JIT compiler can modify code to call a method 3. Inlined code can be invalidated 8IFOJTNFUIPEJOMJOJOHQPTTJCMF

Slide 134

Slide 134 text

1. JIT compiler can know definitions 2. JIT compiler can modify code to call a method 3. Inlined code can be invalidated 8IFOJTNFUIPEJOMJOJOHQPTTJCMF

Slide 135

Slide 135 text

1. JIT compiler can know definitions 2. JIT compiler can modify code to call a method 3. Inlined code can be invalidated 8IFOJTNFUIPEJOMJOJOHQPTTJCMF

Slide 136

Slide 136 text

• Ruby method • called by Ruby method • called by C method • Ruby block • yield-ed by Ruby method • called by C method • C method • called by Ruby method • called by C method .BKPSJOMJOFUBSHFUT

Slide 137

Slide 137 text

• Ruby method • called by Ruby method => easy • called by C method • Ruby block • yield-ed by Ruby method • called by C method • C method • called by Ruby method • called by C method .BKPSJOMJOFUBSHFUT JIT compiler can deal with bytecode easily Method cache can be used for invalidation

Slide 138

Slide 138 text

• Ruby method • called by Ruby method => easy • called by C method • Ruby block • yield-ed by Ruby method => medium • called by C method • C method • called by Ruby method => medium • called by C method .BKPSJOMJOFUBSHFUT yield doesn't have cache Sometimes it's hard to know definitions

Slide 139

Slide 139 text

• Ruby method • called by Ruby method => easy • called by C method => hard • Ruby block • yield-ed by Ruby method => medium • called by C method => hard • C method • called by Ruby method => medium • called by C method => hard .BKPSJOMJOFUBSHFUT There is no cache key for invalidation How to modify C code?

Slide 140

Slide 140 text

3VCZˠ$ˠ3VCZJOMJOJOHQSPCMFN ret = 0 1000000.times do |i| ret += i end ret

Slide 141

Slide 141 text

ret = 0 1000000.times do |i| ret += i end ret Ruby -> C method call medium Integer#times is defined with C 3VCZˠ$ˠ3VCZJOMJOJOHQSPCMFN

Slide 142

Slide 142 text

ret = 0 1000000.times do |i| ret += i end ret Ruby -> C method call medium Integer#times is defined with C C -> Ruby block call hard 3VCZˠ$ˠ3VCZJOMJOJOHQSPCMFN

Slide 143

Slide 143 text

What if... Ruby can be faster than C?

Slide 144

Slide 144 text

What if... Ruby can be faster than C?

Slide 145

Slide 145 text

-FUTEFGJOF*OUFHFSUJNFTXJUI3VCZ https://github.com/rubinius/rubinius/blob/master/core/integer.rb

Slide 146

Slide 146 text

• Ruby method • called by Ruby method => easy • called by C method => hard • Ruby block • yield-ed by Ruby method => medium • called by C method => hard • C method • called by Ruby method => medium • called by C method => hard *JNQMFNFOUFEBQSPUPUZQFUPJOMJOFUIJT https://github.com/k0kubun/ruby/commits/mjit-inline-send-yield

Slide 147

Slide 147 text

5JNFUPCFODINBSL

Slide 148

Slide 148 text

*OUFHFSUJNFTCFODINBSLSFTVMUT Integer#times in C Integer#times in Ruby VM 145.44s 1.00x 156.38s 0.93x JIT time ruby --disable-gems times_loop.rb

Slide 149

Slide 149 text

*OUFHFSUJNFTCFODINBSLSFTVMUT Integer#times in C Integer#times in Ruby VM 145.44s 1.00x 156.38s 0.93x JIT 104.80s 1.39x time ruby --disable-gems times_loop.rb

Slide 150

Slide 150 text

*OUFHFSUJNFTCFODINBSLSFTVMUT Integer#times in C Integer#times in Ruby VM 145.44s 1.00x 156.38s 0.93x JIT 104.80s 1.39x 56.46s 2.56x time ruby --disable-gems times_loop.rb

Slide 151

Slide 151 text

C language is dead

Slide 152

Slide 152 text

• Rails performance is going to be improved • JIT can eliminate many instructions • C language will be useless in the future $PODMVTJPO