The Strange Loop conference is a unique software developer conference in St. Louis featuring excellent speakers and a wide variety of languages and technologies. This interview with Charles discusses his Strange Loop talk "Ruby Mutants", which will explore his Ruby-Java hybrid languages Duby and Juby. Duby is Ruby with static typing and Juby uses Ruby's syntax and dynamic-typing but works directly on the Java type system.
Charles Oliver Nutter (@headius) is well-known for his work on JRuby, the JVM-based implementation of Ruby. During his time at Sun, he has also been an enthusiastic early adopter of the work done by the JVM team for JSR 292 and invokedynamic to allow more flexible method invocation, a key feature needed by dynamic languages. Recently Charles and the rest of the JRuby team left Sun and moved to well-known Ruby powerhouse Engine Yard, which is seeing an increase in demand for applications deployed on JRuby.
Strange Loop: Hi Charles, I was wondering if you could give us an idea of where JRuby stands today in relation to other Ruby implementations. Obviously, it has a Java integration story that others do not, but where does it stand in regards to compatibility and performance? Why would someone choose JRuby vs another implementation?
Charles: As far as being a Ruby implementation, we are the most complete, most compatible alternative Ruby around. We're the only one with production Rails users. And we consider 1.8.6/7 compatibility to be mostly a "solved" problem, modulo the little fixes we'll make forever.
We're also the only alternative impl with demonstrably better performance on real-world applications. Rails is now comfortably faster than Ruby 1.8 for almost all users, and on par with 1.9 even though we haven't started adding any of 1.9-related optimizations to JRuby yet. And on microbenchmarks, we perform even better; fast enough that some MRI-only shops now run JRuby for large data-processing jobs.
Along with performance, JRuby offers real parallel native threads, which allows JRuby to scale much better on modern systems with many cores. Of the alternative impls, only three support parallel threads, only two of those can run Rails, and only JRuby can run it fast. We're the best alternative impl for running real applications right now.
I think JRuby's proven to be a really excellent Ruby implementation.
Strange Loop: In JDK 7, JSR 292 is exploring what features are needed at the JVM level to support dynamic languages. JRuby is perhaps the most visible early adopter for the new invokedynamic bytecode and method handles. It seems that you are seeing significant performance improvements from these features. Can you explain why they are so important for dynamic languages and how they result in performance increases?
JRuby is the first (and still the only) JVM language to have fully-functional invokedynamic support, and the simplicity it brings to dynamic calls is astounding. We have not seen the hoped-for performance boost yet, but the Hotspot engineers have only started to add optimizations to invokedynamic. The truth is that dynamic languages suit many problem domains better than static-typed languages. If they have performance as well, the only penalties you pay are the lack of static-typing guarantees. In today's polyglot world, you should be able to move the bar between your dynamic and static code at will without suffering a perf hit. invokedynamic and similar work will make that possible for JVM languages.
Strange Loop: What other JVM features do you feel are most important? It seems that features like tail calls, fixnum support, and interface injection are examples on the short list. What additional features would make the most difference in JRuby?
Charles: I have a fairly short list of JVM features I'd like to see:
Tail calls: The JVM should support optimized general tail calls. There's actually a patch in the MLVM project that adds this, and I believe there's a JSR being formed to try to get it into Java 7. But it's not there yet, and it's sorely missed.
Interface injection: This is the ability to treat any Object as though it implemented a given interface by providing code to implement that interface at runtime. It's sort of like "runtime extension methods" for the JVM. This is currently in-progress and attached to the invokedynamic JSR, since it's a feature a lot of JVM languages could use. It would allow us, for example, to treat all java.util.List implementers as though they implemented a JRuby-aware "Array" interface and pass through JRuby as though they were always Ruby arrays. It would make it much easier to munge together Java's types with an arbitrary language's types.
Fixnums and/or value types: One of the few places where we're sure to be surpassed on performance is numeric operations. 1 + 1 in JRuby involves a lot more logic than it does for Java, since Java treats that as a primitive "plus" operation against two 32-bit integer primitives and optimizes it down to the fastest-possible native code.
The problem stems from our call logic only supporting Object targets and arguments. This means we generally have to box all values, and so we pay both the cost of doing a dynamic invocation *and* the cost of boxing and unboxing numbers. Other Ruby implementations are able to pass "tagged pointers" around for Fixnums, and only pay a small bitmasking cost before performing math operations. If we had native fixnum support in the JVM, we could theoretically have fully-boxed math operations almost as fast as primitive math. But there's nobody working on this yet.
Delimited continuations (coroutines): Ruby 1.9 has added the ability to spin up "fibers", which are lightweight thread-like entities that do not require a new native thread but which can be branched into and out of at any time. In JRuby, because we don't have any support for branching out of (and preserving) a given call stack, we have to implement fibers with native threads. If the JVM had support for continuations (really we only need "delimited" continuations), we'd be able to implement fibers much more efficiently by just swapping call stacks at will. There is a working patch for continuation support in MLVM, but no plans to move it into Java 7 due to unresolved security questions.
Strange Loop: Many people were surprised by Engine Yard's move to hire the three primary JRuby developers. Why does Engine Yard see a need to increase > their commitment to JRuby?
Charles: Engine Yard approached us because, simply put, they were seeing a lot of demand for JRuby. They were also interested in growing the Ruby world, and getting Java developers to use Ruby is probably the fastest way to do that. We're very excited about the move to Engine Yard and the response we've received from Rubyists, JRubyists, and JVM language enthusiasts alike. It's going to be great to have a Ruby-focused company driving JRuby forward, and it also means we can collaborate with everyone in the Java world interested in JRuby much more easily. It's a win for everyone involved.
Strange Loop: What does the future hold for JRuby and Java integration? I assume the Duby and Juby projects you will be talking about at Strange Loop are ways of exploring alternatives for future integration?
Charles: They most definitely are. Duby is an exploration of how a static-typed "Ruby-like" language might look and feel on the JVM, and I think I've been able to prove so far that with only minor modifications you can get a lot of Ruby's beauty out of a static-typed alternative. The Juby project is my attempt to explore an entirely invokedynamic-based language, to see how simple the call protocols can get and how tight the integration with normal Java types and objects can be. Both of these will feed into JRuby work.
As far as JRuby's built-in Java integration, we're now filling the remaining gaps when compared to languages like Groovy or Scala. Up to now it has been impossible to generate a "normal" Java class from Ruby code, which meant that reflective or annotative APIs like JPA or JAX-RS could not be implemented with JRuby. But after only a few hours work, JRuby's master branch already includes most of the plumbing needed to make Ruby objects actually *be* Java objects, with normal-looking classes that are reflectable, have normal signatures, and support annotations. Soon we'll explore having an offline compiler that does the same, with early work in the "ruby2java" project. And once we can create normal Java classes, there's essentially no Java integration feature we won't be able to support. JRuby will be shoulder-to-shoulder with Groovy as far as Java is concerned, and we'll still be true to Ruby.
Strange Loop: Thanks Charles! I can't wait to hear your talk at Strange Loop!
Find out more about Strange Loop: