Ruby on the JVM

  • 1,092 views
Uploaded on

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

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,092
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
9
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Ruby on the JVM Kresten Krab Thorup, Ph.D. CTO, Trifork
  • 2. A bit of history... Smalltalk Self OTI Smalltalk Strongtalk VisualAge HotSpot IBM Java Sun IBM
  • 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. 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. 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. “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. 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. HotRuby Architecture shared meta model interpreter compiler ~MRI performance ~2.5 x YARV performance
  • 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. 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. Naive Implementation class RubyObject { RubyClass isa; HashTable<String,RubyObject> ivars; boolean frozen, tainted; }
  • 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. Naive Implementation class Callable { RubyObject call(RubyObject self, RubyObject[] args, RubyBlock block, CallContext ctx); }
  • 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. Naive Implementation Ruby level Java level
  • 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. 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. 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. Reduce Footprint • Reduce size of heap for “active state” in a virtual machine • Reduce “object churn”, i.e. rate of generated garbage.
  • 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. 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. 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. 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. 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. 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. Thanks
  • 27. The Ruby “Freak Show” ... getting started
  • 28. Super Strange def doit(x, y) super.doit(x, y) end
  • 29. Super Strange def doit(x, y) super(x, y) end
  • 30. Super Strange def doit(x, y) super end
  • 31. Super Strange def doit(x, y=2, z=3) super end
  • 32. Super Strange def doit(x, y=super, z=3) x+y+z end
  • 33. Super Strange def doit(x, y=super(x,y,z), z=3) x+y+z end
  • 34. Thanks