Ruby on the JVM
  Kresten Krab Thorup, Ph.D.
         CTO, Trifork
A bit of history...
  Smalltalk
    Self            OTI Smalltalk
 Strongtalk          VisualAge

  HotSpot             IB...
Adaptive Optimizations
• Key insight:   The VM knows more about
  your program than you do.
• Consequence: Let the VM adap...
Time/Space Trade Off
• Classical compiler “ideology”
 • “ahead of time” compilers don’t know
    which parts of the code t...
The Ruby Nature
• Program is created as it is being
  executed
 • Class / module declarations are really
   statements, no...
“Just In Time” VMs
• For interpreted-style languages, perform
  compilation when the program definition is
  known.
• AFAIK...
The “HotRuby” project
• Explore a “Server VM” for Ruby
  based on Java
• Assume “long running processes” where we
  can af...
HotRuby Architecture
                  shared meta
                     model



    interpreter                 compiler
...
Design Philosophy

• Develop compiler and interpreter in
  parallel, and
• Favor compiler in the design of the runtime
  m...
Major Head Aches
• Method invocation
 • Calling “virtual” methods is slow
 • Program can change in many ways while
    run...
Naive Implementation

class RubyObject {
   RubyClass isa;
   HashTable<String,RubyObject> ivars;
   boolean frozen, taint...
Naive Implementation
class RubyModule extends RubyObject {
  RubyVM vm;
  List<RubyModule> included_modules;
  HashTable<S...
Naive Implementation

class Callable {
   RubyObject call(RubyObject self,
                   RubyObject[] args,
         ...
Naive Implementation
  def m(obj)
    obj.foo(1, BAR)
  end

... translates into something like ...
  ctx = new MethodActi...
Naive Implementation

       Ruby level


       Java level
Optimizing Calls

• Special-case common method names for
  core classes (new, +, -, [], ...): They turn into
  Java-level ...
Method Specialization
• Compiled code is “specialized” for the
  receiving type,
  • making self-calls non virtual,
  • re...
Compiled Lookup
• With the “Naive” implementation, method
  lookup is data-driven (HashTable).
• Compiled lookup means tha...
Reduce Footprint

• Reduce size of heap for “active state” in a
  virtual machine
• Reduce “object churn”, i.e. rate of ge...
Reducing Footprint
• Java objects already have an “isa” pointer!
  The implicit class reference.
• Use Java-level instance...
HotRuby Object
class RubyFoo {
   ObjectState state = null;
   RubyClass isa()
      { return state==null
          ? Ruby...
HotRuby @ivars
• Generate Java classes lazily, upon first
  instantiation.
• At that point, analyze all applicable methods
...
Reducing Footprint
• The “Naive” implementation has an
  overhead per object of
     20 bytes + ~20 bytes / ivar
• HotRuby...
Use Java-Level locals
• The “cost” for having MethodActivation
  objects is both
 • The memory it consumes
 • The fact tha...
HotRuby Status

• Runs basic Ruby programs (most
  importantly runit)
 • No Continuations, ObjectSpace,
    debugger, ... ...
Thanks
The Ruby
“Freak Show”
  ... getting started
Super Strange


def doit(x, y)
    super.doit(x, y)
end
Super Strange


def doit(x, y)
    super(x, y)
end
Super Strange


def doit(x, y)
    super
end
Super Strange


def doit(x, y=2, z=3)
    super
end
Super Strange


def doit(x, y=super, z=3)
    x+y+z
end
Super Strange


def doit(x, y=super(x,y,z), z=3)
    x+y+z
end
Thanks
Upcoming SlideShare
Loading in...5
×

Ruby on the JVM

1,154

Published on

In this talk I describe some challenges in making my hotruby, a JVM-based Ruby implementation that was never finished.

http://github.com/krestenkrab/hotruby

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,154
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
10
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • Transcript of "Ruby on the JVM"

    1. 1. Ruby on the JVM Kresten Krab Thorup, Ph.D. CTO, Trifork
    2. 2. A bit of history... Smalltalk Self OTI Smalltalk Strongtalk VisualAge HotSpot IBM Java Sun IBM
    3. 3. Adaptive Optimizations • Key insight: The VM knows more about your program than you do. • Consequence: Let the VM adapt to program’s behavior • VM will observe, tally and measure • feed information into successive optimizations
    4. 4. Time/Space Trade Off • Classical compiler “ideology” • “ahead of time” compilers don’t know which parts of the code to optimize • gcc -O0 ... -O6 • Adaptive VMs • Affords letting the program run for a while to see where optimizations will pay off.
    5. 5. The Ruby Nature • Program is created as it is being executed • Class / module declarations are really statements, not declarations. • Programming style employs meta programming extensively • Very similar to Java, just “worse” :-)
    6. 6. “Just In Time” VMs • For interpreted-style languages, perform compilation when the program definition is known. • AFAIK Strongtalk/HotSpot brought the innovation of a two-level VM: • start interpreted (running byte code) • optimize adaptively
    7. 7. The “HotRuby” project • Explore a “Server VM” for Ruby based on Java • Assume “long running processes” where we can afford “slow start”. • Assume aggressive memory usage • Exploit knowledge of how the JVM optimizes programs
    8. 8. HotRuby Architecture shared meta model interpreter compiler ~MRI performance ~2.5 x YARV performance
    9. 9. Design Philosophy • Develop compiler and interpreter in parallel, and • Favor compiler in the design of the runtime meta model • Make trade-offs that reduce memory usage • Write as much as possible in Ruby itself
    10. 10. Major Head Aches • Method invocation • Calling “virtual” methods is slow • Program can change in many ways while running • Memory management • Garbage collection is a resource hog
    11. 11. Naive Implementation class RubyObject { RubyClass isa; HashTable<String,RubyObject> ivars; boolean frozen, tainted; }
    12. 12. Naive Implementation class RubyModule extends RubyObject { RubyVM vm; List<RubyModule> included_modules; HashTable<String,Callable> imethods; HashTable<String,Callable> mmethods; HashTable<String,RubyObject> constants; } class RubyClass extends RubyModule { RubyClass super_class; }
    13. 13. Naive Implementation class Callable { RubyObject call(RubyObject self, RubyObject[] args, RubyBlock block, CallContext ctx); }
    14. 14. Naive Implementation def m(obj) obj.foo(1, BAR) end ... translates into something like ... ctx = new MethodActivation(...); ctx.set_local(args[0]); obj = ctx.get_local(0) one = ctx.new_fixnum(1); bar = ctx.lookup_const(“BAR”); callable = obj.isa.imethods.get(“foo”); callable.call(obj, [one, bar], null, ctx)
    15. 15. Naive Implementation Ruby level Java level
    16. 16. Optimizing Calls • Special-case common method names for core classes (new, +, -, [], ...): They turn into Java-level virtual calls. • Compiled code is “specialized”, ... • Method lookup is “compiled”, ...
    17. 17. Method Specialization • Compiled code is “specialized” for the receiving type, • making self-calls non virtual, • reducing public/private/protected checks: Security-checks happen at method- lookup, not invocation time. • making constant lookups really constant.
    18. 18. Compiled Lookup • With the “Naive” implementation, method lookup is data-driven (HashTable). • Compiled lookup means that we dynamically generate/modify code, as the lookup table changes. • Allows the JVM’s optimizing compiler to “know” how/when to eliminate or inline lookups.
    19. 19. Reduce Footprint • Reduce size of heap for “active state” in a virtual machine • Reduce “object churn”, i.e. rate of generated garbage.
    20. 20. Reducing Footprint • Java objects already have an “isa” pointer! The implicit class reference. • Use Java-level instance variables (in most cases) • Eliminate the arguments array for method invocations (in most cases). • Use Java-level local variables, removing the need for a “MethodActivation” object for each method call.
    21. 21. HotRuby Object class RubyFoo { ObjectState state = null; RubyClass isa() { return state==null ? RubyClassFoo.class_object : state.singletonClass; } } class ObjectState { boolean frozen, tained; RubyClass singletonClass; HashTable<String,RubyObject> ivars; }
    22. 22. HotRuby @ivars • Generate Java classes lazily, upon first instantiation. • At that point, analyze all applicable methods for reference to @ivars • Generate Java-level ivars for all such references. • Additional ivars go into ObjectState’s hash table.
    23. 23. Reducing Footprint • The “Naive” implementation has an overhead per object of 20 bytes + ~20 bytes / ivar • HotRuby ideally reduces this to 12 bytes + 4 bytes / ivar • Heap of 100.000 object with an average 3 ivars => 83% memory saving.
    24. 24. Use Java-Level locals • The “cost” for having MethodActivation objects is both • The memory it consumes • The fact that such memory needs to be garbage collected • Fall-back to MethodActivation object strategy for methods that call eval (and friends), and for local variables referenced from inner blocks.
    25. 25. HotRuby Status • Runs basic Ruby programs (most importantly runit) • No Continuations, ObjectSpace, debugger, ... and many core classes • Performance at 2.5 x YARV • No, it does not run Rails.
    26. 26. Thanks
    27. 27. The Ruby “Freak Show” ... getting started
    28. 28. Super Strange def doit(x, y) super.doit(x, y) end
    29. 29. Super Strange def doit(x, y) super(x, y) end
    30. 30. Super Strange def doit(x, y) super end
    31. 31. Super Strange def doit(x, y=2, z=3) super end
    32. 32. Super Strange def doit(x, y=super, z=3) x+y+z end
    33. 33. Super Strange def doit(x, y=super(x,y,z), z=3) x+y+z end
    34. 34. Thanks
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×