Accelerating Ruby
                              with LLVM
                                 Evan Phoenix
                  ...
RUBY


Tuesday, October 6, 2009
RUBY
                           Strongly, dynamically typed




Tuesday, October 6, 2009
RUBY
                           Unified Model




Tuesday, October 6, 2009
RUBY
                           Everything is an object




Tuesday, October 6, 2009
RUBY
                           3.class # => Fixnum




Tuesday, October 6, 2009
RUBY
                           Every code context is equal




Tuesday, October 6, 2009
RUBY
                           Every context is a method




Tuesday, October 6, 2009
RUBY
                           Garbage Collected




Tuesday, October 6, 2009
RUBY
                           A lot of syntax




Tuesday, October 6, 2009
RUBY
                           Strongly, dynamically typed Every code context is equal
                                 U...
Rubinius


Tuesday, October 6, 2009
Rubinius
                           Started in 2006




Tuesday, October 6, 2009
Rubinius
                           Build a ruby environment for fun




Tuesday, October 6, 2009
Rubinius
                           Unlike most “scripting” languages,
                           write as much in ruby as...
Rubinius
                  Core functionality of perl/python/ruby in C,
                      NOT in their respective lang...
Rubinius
                           C => ruby => C => ruby




Tuesday, October 6, 2009
Rubinius
                           Language boundaries suck




Tuesday, October 6, 2009
Rubinius
                                Started in 2006
                                  Built for fun
                 ...
Evolution


Tuesday, October 6, 2009
Evolution
                           100% ruby prototype running on 1.8




Tuesday, October 6, 2009
Evolution
                           Hand translated VM to C




Tuesday, October 6, 2009
Evolution
                           Rewrote VM in C++




Tuesday, October 6, 2009
Evolution
                           Switch away from stackless




Tuesday, October 6, 2009
Evolution
                           Experimented with handwritten
                                 assembler for x86



T...
Evolution
                           Switch to LLVM for JIT




Tuesday, October 6, 2009
Evolution
                            100% ruby prototype      Switch away from stackless
                           Hand ...
Features


Tuesday, October 6, 2009
Features
                           Bytecode VM




Tuesday, October 6, 2009
Features
                           Simple interface to native code




Tuesday, October 6, 2009
Features
                           Accurate, generational garbage collector




Tuesday, October 6, 2009
Features
                           Integrated FFI API




Tuesday, October 6, 2009
Features
               Bytecode VM        Generational GC
         Interface to native code  Integrated FFI


Tuesday, Oc...
Benchmarks


Tuesday, October 6, 2009
def foo()
                             ary = []
                             100.times { |i| ary << i }
                  ...
Seconds
                             9


                                  8.02


                           6.75

       ...
def foo()
                             hsh = {}
                             100.times { |i| hsh[i] = 0 }
                ...
Seconds
                            30



                                                25.36

                         ...
def foo()
                             hsh = { 47 => true }
                             100.times { |i| hsh[i] }
        ...
Seconds
                             7


                                                6.26


                          ...
Early LLVM Usage


Tuesday, October 6, 2009
Early LLVM Usage
                           Compiled all methods up front




Tuesday, October 6, 2009
Early LLVM Usage
                           Simple opcode-to-function translation
                                       w...
Early LLVM Usage
                           Startup went from 0.3s to 80s




Tuesday, October 6, 2009
Early LLVM Usage
                               Compiled all methods upfront
                            Simple opcode-to-...
True JIT


Tuesday, October 6, 2009
True JIT
                            JIT Goals




Tuesday, October 6, 2009
True JIT
                                       JIT Goals
                           Choose methods that benefit the most

...
True JIT
                                           JIT Goals
                           Compiling has minimum impact on p...
True JIT
                                           JIT Goals
                           Ability to make intelligent front...
Choosing Methods


Tuesday, October 6, 2009
Choosing Methods
                              Simple call counters




Tuesday, October 6, 2009
Choosing Methods
                           When counter trips, the fun starts




Tuesday, October 6, 2009
Choosing Methods
                             Room for improvement




Tuesday, October 6, 2009
Choosing Methods
                             Room for improvement
                              Increment counters in loo...
Choosing Methods
                               Room for improvement
                            Weigh different invocatio...
Choosing Methods
                               Simple counters        Room for improvement
                           Tri...
Which Method?


Tuesday, October 6, 2009
Which Method?
                           Leaf methods trip quickly




Tuesday, October 6, 2009
Which Methods?
                            Leaf methods trip quickly
                             Consider the whole calls...
Which Methods?
                            Leaf methods trip quickly
                             Pick a parent expecting ...
Which Method?
                             Leaf methods trip
                            Consider the callstack
          ...
Minimal Impact


Tuesday, October 6, 2009
Minimal Impact
                            After the counters trip




Tuesday, October 6, 2009
Minimal Impact
                             Queue the method




Tuesday, October 6, 2009
Minimal Impact
                           Background thread drains queue




Tuesday, October 6, 2009
Minimal Impact
                           Frontend, passes, codegen in background




Tuesday, October 6, 2009
Minimal Impact
                             Install JIT’d function




Tuesday, October 6, 2009
Minimal Impact
                             Install JIT’d function
                             Requires GC interaction


...
Minimal Impact
                  Trip the counters Compile in background
                  Queue the method Install functi...
Good Decisions


Tuesday, October 6, 2009
Good Decisions
                    Naive translation yields fixed improvement




Tuesday, October 6, 2009
Good Decisions
                           Performance shifts to method dispatch




Tuesday, October 6, 2009
Good Decisions
                           Improve optimization horizon




Tuesday, October 6, 2009
Good Decisions
                           Inline using type feedback




Tuesday, October 6, 2009
Good Decisions
                            Naive translation sucks     Performance in dispatch
                           ...
Type Feedback


Tuesday, October 6, 2009
Type Feedback
                           Frontend translates to IR




Tuesday, October 6, 2009
Type Feedback
                           Read InlineCache information




Tuesday, October 6, 2009
Type Feedback
                           InlineCaches contain profiling info




Tuesday, October 6, 2009
Type Feedback
                           Use profiling to drive inlining!




Tuesday, October 6, 2009
Type Feedback
                           Frontend generates IR    InlineCaches have profiling
                            R...
Inlining


Tuesday, October 6, 2009
Inlining
                           Profiling info shows a dominant class




Tuesday, October 6, 2009
2
                            1%




                           1 class
                            98%



Tuesday, Octobe...
Inlining
                           Lookup method in compiler




Tuesday, October 6, 2009
Inlining
                           For native functions, emit direct call




Tuesday, October 6, 2009
Inlining
                           For FFI, inline conversions and call




Tuesday, October 6, 2009
Inlining
                           Find dominant class
                                                 Emit direct calls...
Inlining Ruby


Tuesday, October 6, 2009
Inlining Ruby
                           Policy decides on inlining




Tuesday, October 6, 2009
Inlining Ruby
                           Drive sub-frontend at call site




Tuesday, October 6, 2009
Inlining Ruby
                           All inlining occurs in the frontend




Tuesday, October 6, 2009
Inlining Ruby
                           Generated IR preserves runtime data




Tuesday, October 6, 2009
Inlining Ruby
                           Generated IR preserves runtime data
                                   GC roots, ...
Inlining Ruby
                           No AST between bytecode and IR




Tuesday, October 6, 2009
Inlining Ruby
                           No AST between bytecode and IR
                           Fast, but limits the ab...
Inlining Ruby
                             Policy decides     Preserve runtime data
                           Drive sub-f...
LLVM


Tuesday, October 6, 2009
LLVM
                           IR uses operand stack




Tuesday, October 6, 2009
LLVM
                           IR uses operand stack
                           Highlevel data flow not in SSA




Tuesday...
LLVM
                           IR uses operand stack
                           Passes eliminate redundencies




Tuesday...
LLVM
                           IR uses operand stack
                           Makes GC stack marking easy




Tuesday, ...
LLVM
                            IR uses operand stack
                           nocapture improves propagation




Tuesd...
LLVM
                           Exceptions via sentinal value




Tuesday, October 6, 2009
LLVM
                            Exceptions via sentinal value
                           Nested handlers use branches for...
LLVM
                           Exceptions via sentinal value
                            Inlining exposes redundant check...
LLVM
                           Inline guards




Tuesday, October 6, 2009
LLVM
                           Inline guards
                           Simple type guards




Tuesday, October 6, 2009
if(obj->class->class_id ==
                              <integer constant>) {


Tuesday, October 6, 2009
LLVM
                                     Inline guards
                           Custom AA pass for guard elimination


...
LLVM
                                     Inline guards
                           Teach pointsToConstantMemory about...

...
if(obj->class->class_id ==
                              <integer constant>) {


Tuesday, October 6, 2009
if(obj->class->class_id ==
                              <integer constant>) {


Tuesday, October 6, 2009
LLVM
                           Maximizing constant propagation




Tuesday, October 6, 2009
LLVM
                           Maximizing constant propagation
                            Type failures shouldn’t contri...
if(obj->class->class_id == 0x33) {
                             val = 0x7;
                           } else {
           ...
if(obj->class->class_id == 0x33) {
                             val = 0x7;
                           } else {
           ...
LLVM
                           Maximizing constant propagation
                                Makes JIT similar to traci...
LLVM
                           Use overflow intrinsics




Tuesday, October 6, 2009
LLVM
                                Use overflow intrinsics
                           Custom pass to fold constants argum...
LLVM
                           AA knowledge for tagged pointers




Tuesday, October 6, 2009
LLVM
                           AA knowledge of tagged pointers
                                0x5 is 2 as a tagged point...
LLVM
                             Not in SSA form       Maximize constants
                           Simplistic exception...
Issues


Tuesday, October 6, 2009
Issues
                           How to link with LLVM?




Tuesday, October 6, 2009
Issues
                           How to link with LLVM?
                             An important SCM issue




Tuesday, ...
Issues
                           Ugly, confusing IR from frontend




Tuesday, October 6, 2009
Issues
                           instcombine confuses basicaa




Tuesday, October 6, 2009
Issues
                           Operand stack confuses AA




Tuesday, October 6, 2009
Issues
                           Inability to communicate semantics




Tuesday, October 6, 2009
Object* new_object(state)




Tuesday, October 6, 2009
Returned pointer aliases nothing

                                 Only modifies state

                                   ...
Issues
                                 Ugly IR          AA confusion
                           Linking with LLVM   Highl...
Thanks!

                                http://rubini.us
                           ephoenix@engineyard.com


Tuesday, Oc...
Upcoming SlideShare
Loading in …5
×

Accelerating Ruby with LLVM

7,043 views

Published on

Presented at the LLVM developers meeting 2009, shows the Rubinius architecture and how it makes use of LLVM to compile Ruby to machine code.

Published in: Technology, Education
0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,043
On SlideShare
0
From Embeds
0
Number of Embeds
183
Actions
Shares
0
Downloads
119
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

Accelerating Ruby with LLVM

  1. 1. Accelerating Ruby with LLVM Evan Phoenix Oct 2, 2009 Tuesday, October 6, 2009
  2. 2. RUBY Tuesday, October 6, 2009
  3. 3. RUBY Strongly, dynamically typed Tuesday, October 6, 2009
  4. 4. RUBY Unified Model Tuesday, October 6, 2009
  5. 5. RUBY Everything is an object Tuesday, October 6, 2009
  6. 6. RUBY 3.class # => Fixnum Tuesday, October 6, 2009
  7. 7. RUBY Every code context is equal Tuesday, October 6, 2009
  8. 8. RUBY Every context is a method Tuesday, October 6, 2009
  9. 9. RUBY Garbage Collected Tuesday, October 6, 2009
  10. 10. RUBY A lot of syntax Tuesday, October 6, 2009
  11. 11. RUBY Strongly, dynamically typed Every code context is equal Unified model Every context is a method Everything is an object Garbage collected 3.class A lot of syntax Tuesday, October 6, 2009
  12. 12. Rubinius Tuesday, October 6, 2009
  13. 13. Rubinius Started in 2006 Tuesday, October 6, 2009
  14. 14. Rubinius Build a ruby environment for fun Tuesday, October 6, 2009
  15. 15. Rubinius Unlike most “scripting” languages, write as much in ruby as possible Tuesday, October 6, 2009
  16. 16. Rubinius Core functionality of perl/python/ruby in C, NOT in their respective language. Tuesday, October 6, 2009
  17. 17. Rubinius C => ruby => C => ruby Tuesday, October 6, 2009
  18. 18. Rubinius Language boundaries suck Tuesday, October 6, 2009
  19. 19. Rubinius Started in 2006 Built for fun Turtles all the way down Tuesday, October 6, 2009
  20. 20. Evolution Tuesday, October 6, 2009
  21. 21. Evolution 100% ruby prototype running on 1.8 Tuesday, October 6, 2009
  22. 22. Evolution Hand translated VM to C Tuesday, October 6, 2009
  23. 23. Evolution Rewrote VM in C++ Tuesday, October 6, 2009
  24. 24. Evolution Switch away from stackless Tuesday, October 6, 2009
  25. 25. Evolution Experimented with handwritten assembler for x86 Tuesday, October 6, 2009
  26. 26. Evolution Switch to LLVM for JIT Tuesday, October 6, 2009
  27. 27. Evolution 100% ruby prototype Switch away from stackless Hand translated VM to C Experiment with assembler Rewrote VM in C++ Switch to LLVM for JIT Tuesday, October 6, 2009
  28. 28. Features Tuesday, October 6, 2009
  29. 29. Features Bytecode VM Tuesday, October 6, 2009
  30. 30. Features Simple interface to native code Tuesday, October 6, 2009
  31. 31. Features Accurate, generational garbage collector Tuesday, October 6, 2009
  32. 32. Features Integrated FFI API Tuesday, October 6, 2009
  33. 33. Features Bytecode VM Generational GC Interface to native code Integrated FFI Tuesday, October 6, 2009
  34. 34. Benchmarks Tuesday, October 6, 2009
  35. 35. def foo() ary = [] 100.times { |i| ary << i } end 300,000 times Tuesday, October 6, 2009
  36. 36. Seconds 9 8.02 6.75 5.90 5.30 4.5 3.60 2.25 2.59 0 1.8 1.9 rbx rbx jit rbx jit +blocks Tuesday, October 6, 2009
  37. 37. def foo() hsh = {} 100.times { |i| hsh[i] = 0 } end 100,000 times Tuesday, October 6, 2009
  38. 38. Seconds 30 25.36 22.5 15 12.54 12.01 7.5 4.85 5.26 0 1.8 1.9 rbx rbx jit rbx jit +blocks Tuesday, October 6, 2009
  39. 39. def foo() hsh = { 47 => true } 100.times { |i| hsh[i] } end 100,000 times Tuesday, October 6, 2009
  40. 40. Seconds 7 6.26 5.25 3.5 3.64 2.68 2.66 2.09 1.75 0 1.8 1.9 rbx rbx jit rbx jit +blocks Tuesday, October 6, 2009
  41. 41. Early LLVM Usage Tuesday, October 6, 2009
  42. 42. Early LLVM Usage Compiled all methods up front Tuesday, October 6, 2009
  43. 43. Early LLVM Usage Simple opcode-to-function translation with inlining Tuesday, October 6, 2009
  44. 44. Early LLVM Usage Startup went from 0.3s to 80s Tuesday, October 6, 2009
  45. 45. Early LLVM Usage Compiled all methods upfront Simple opcode-to-function translation Startup from 0.3s to 80s Tuesday, October 6, 2009
  46. 46. True JIT Tuesday, October 6, 2009
  47. 47. True JIT JIT Goals Tuesday, October 6, 2009
  48. 48. True JIT JIT Goals Choose methods that benefit the most Tuesday, October 6, 2009
  49. 49. True JIT JIT Goals Compiling has minimum impact on performance Tuesday, October 6, 2009
  50. 50. True JIT JIT Goals Ability to make intelligent frontend decisions Tuesday, October 6, 2009
  51. 51. Choosing Methods Tuesday, October 6, 2009
  52. 52. Choosing Methods Simple call counters Tuesday, October 6, 2009
  53. 53. Choosing Methods When counter trips, the fun starts Tuesday, October 6, 2009
  54. 54. Choosing Methods Room for improvement Tuesday, October 6, 2009
  55. 55. Choosing Methods Room for improvement Increment counters in loops Tuesday, October 6, 2009
  56. 56. Choosing Methods Room for improvement Weigh different invocations differently Tuesday, October 6, 2009
  57. 57. Choosing Methods Simple counters Room for improvement Trip the counters, do it Increment in loops Weigh invocations Tuesday, October 6, 2009
  58. 58. Which Method? Tuesday, October 6, 2009
  59. 59. Which Method? Leaf methods trip quickly Tuesday, October 6, 2009
  60. 60. Which Methods? Leaf methods trip quickly Consider the whole callstack Tuesday, October 6, 2009
  61. 61. Which Methods? Leaf methods trip quickly Pick a parent expecting inlining Tuesday, October 6, 2009
  62. 62. Which Method? Leaf methods trip Consider the callstack Find a parent Tuesday, October 6, 2009
  63. 63. Minimal Impact Tuesday, October 6, 2009
  64. 64. Minimal Impact After the counters trip Tuesday, October 6, 2009
  65. 65. Minimal Impact Queue the method Tuesday, October 6, 2009
  66. 66. Minimal Impact Background thread drains queue Tuesday, October 6, 2009
  67. 67. Minimal Impact Frontend, passes, codegen in background Tuesday, October 6, 2009
  68. 68. Minimal Impact Install JIT’d function Tuesday, October 6, 2009
  69. 69. Minimal Impact Install JIT’d function Requires GC interaction Tuesday, October 6, 2009
  70. 70. Minimal Impact Trip the counters Compile in background Queue the method Install function pointer Tuesday, October 6, 2009
  71. 71. Good Decisions Tuesday, October 6, 2009
  72. 72. Good Decisions Naive translation yields fixed improvement Tuesday, October 6, 2009
  73. 73. Good Decisions Performance shifts to method dispatch Tuesday, October 6, 2009
  74. 74. Good Decisions Improve optimization horizon Tuesday, October 6, 2009
  75. 75. Good Decisions Inline using type feedback Tuesday, October 6, 2009
  76. 76. Good Decisions Naive translation sucks Performance in dispatch Inline using type feedback Improve optimizations Tuesday, October 6, 2009
  77. 77. Type Feedback Tuesday, October 6, 2009
  78. 78. Type Feedback Frontend translates to IR Tuesday, October 6, 2009
  79. 79. Type Feedback Read InlineCache information Tuesday, October 6, 2009
  80. 80. Type Feedback InlineCaches contain profiling info Tuesday, October 6, 2009
  81. 81. Type Feedback Use profiling to drive inlining! Tuesday, October 6, 2009
  82. 82. Type Feedback Frontend generates IR InlineCaches have profiling Reads InlineCaches Use profiling to drive inlining! Tuesday, October 6, 2009
  83. 83. Inlining Tuesday, October 6, 2009
  84. 84. Inlining Profiling info shows a dominant class Tuesday, October 6, 2009
  85. 85. 2 1% 1 class 98% Tuesday, October 6, 2009
  86. 86. Inlining Lookup method in compiler Tuesday, October 6, 2009
  87. 87. Inlining For native functions, emit direct call Tuesday, October 6, 2009
  88. 88. Inlining For FFI, inline conversions and call Tuesday, October 6, 2009
  89. 89. Inlining Find dominant class Emit direct calls if possible Lookup method Tuesday, October 6, 2009
  90. 90. Inlining Ruby Tuesday, October 6, 2009
  91. 91. Inlining Ruby Policy decides on inlining Tuesday, October 6, 2009
  92. 92. Inlining Ruby Drive sub-frontend at call site Tuesday, October 6, 2009
  93. 93. Inlining Ruby All inlining occurs in the frontend Tuesday, October 6, 2009
  94. 94. Inlining Ruby Generated IR preserves runtime data Tuesday, October 6, 2009
  95. 95. Inlining Ruby Generated IR preserves runtime data GC roots, backtraces, etc Tuesday, October 6, 2009
  96. 96. Inlining Ruby No AST between bytecode and IR Tuesday, October 6, 2009
  97. 97. Inlining Ruby No AST between bytecode and IR Fast, but limits the ability to generate better IR Tuesday, October 6, 2009
  98. 98. Inlining Ruby Policy decides Preserve runtime data Drive sub-frontend Generates fast, ugly IR Tuesday, October 6, 2009
  99. 99. LLVM Tuesday, October 6, 2009
  100. 100. LLVM IR uses operand stack Tuesday, October 6, 2009
  101. 101. LLVM IR uses operand stack Highlevel data flow not in SSA Tuesday, October 6, 2009
  102. 102. LLVM IR uses operand stack Passes eliminate redundencies Tuesday, October 6, 2009
  103. 103. LLVM IR uses operand stack Makes GC stack marking easy Tuesday, October 6, 2009
  104. 104. LLVM IR uses operand stack nocapture improves propagation Tuesday, October 6, 2009
  105. 105. LLVM Exceptions via sentinal value Tuesday, October 6, 2009
  106. 106. LLVM Exceptions via sentinal value Nested handlers use branches for control Tuesday, October 6, 2009
  107. 107. LLVM Exceptions via sentinal value Inlining exposes redundant checks Tuesday, October 6, 2009
  108. 108. LLVM Inline guards Tuesday, October 6, 2009
  109. 109. LLVM Inline guards Simple type guards Tuesday, October 6, 2009
  110. 110. if(obj->class->class_id == <integer constant>) { Tuesday, October 6, 2009
  111. 111. LLVM Inline guards Custom AA pass for guard elimination Tuesday, October 6, 2009
  112. 112. LLVM Inline guards Teach pointsToConstantMemory about... Tuesday, October 6, 2009
  113. 113. if(obj->class->class_id == <integer constant>) { Tuesday, October 6, 2009
  114. 114. if(obj->class->class_id == <integer constant>) { Tuesday, October 6, 2009
  115. 115. LLVM Maximizing constant propagation Tuesday, October 6, 2009
  116. 116. LLVM Maximizing constant propagation Type failures shouldn’t contribute values Tuesday, October 6, 2009
  117. 117. if(obj->class->class_id == 0x33) { val = 0x7; } else { val = send_msg(state, obj, ...); } Tuesday, October 6, 2009
  118. 118. if(obj->class->class_id == 0x33) { val = 0x7; } else { return uncommon(state); } Tuesday, October 6, 2009
  119. 119. LLVM Maximizing constant propagation Makes JIT similar to tracing Tuesday, October 6, 2009
  120. 120. LLVM Use overflow intrinsics Tuesday, October 6, 2009
  121. 121. LLVM Use overflow intrinsics Custom pass to fold constants arguments Tuesday, October 6, 2009
  122. 122. LLVM AA knowledge for tagged pointers Tuesday, October 6, 2009
  123. 123. LLVM AA knowledge of tagged pointers 0x5 is 2 as a tagged pointer Tuesday, October 6, 2009
  124. 124. LLVM Not in SSA form Maximize constants Simplistic exceptions Use overflow Inlining guards Tagged pointer AA Tuesday, October 6, 2009
  125. 125. Issues Tuesday, October 6, 2009
  126. 126. Issues How to link with LLVM? Tuesday, October 6, 2009
  127. 127. Issues How to link with LLVM? An important SCM issue Tuesday, October 6, 2009
  128. 128. Issues Ugly, confusing IR from frontend Tuesday, October 6, 2009
  129. 129. Issues instcombine confuses basicaa Tuesday, October 6, 2009
  130. 130. Issues Operand stack confuses AA Tuesday, October 6, 2009
  131. 131. Issues Inability to communicate semantics Tuesday, October 6, 2009
  132. 132. Object* new_object(state) Tuesday, October 6, 2009
  133. 133. Returned pointer aliases nothing Only modifies state If return value is unused, remove the call Semi-pure? Tuesday, October 6, 2009
  134. 134. Issues Ugly IR AA confusion Linking with LLVM Highlevel semantics Tuesday, October 6, 2009
  135. 135. Thanks! http://rubini.us ephoenix@engineyard.com Tuesday, October 6, 2009

×