InfoQ

InfoQ

Article

My Bookmarks

Login or Register to enable bookmarks for unlimited time.

The content has been bookmarked!

There was an error bookmarking this content! Please retry.

The State of JRuby: 1.5, AOT, Java 7

Posted by Werner Schuster on Jun 02, 2010

Sections
Development
Topics
Ruby ,
Runtimes ,
Java ,
JRuby
Tags
JRuby ,
Ruby1.9 ,
JVM

JRuby 1.5 is out, and InfoQ used that opportunity to catch up with JRuby's Charles Nutter to talk about the big changes in the release, the future of JRuby on the current and future JVMs, and more.

InfoQ What's the state of AOT in JRuby 1.5?

We've always had an ahead-of-time compiler, to produce pre-compiled Ruby code in .class files. But there were a few things missing:
* Those precompiled files would go on to generate "invokers", generated code stubs to bind all the methods and blocks in the file. This caused an additional classloading hit while simultaneously preventing precompiled scripts from working in environments where bytecode generation was forbidden (like applets or Android).
* There was no way to produce "real" Java classes. The .class files produced were 1:1 with .rb files, to provide a nice mechanism for precompiling scripts without generating scads of output. But in practice, that didn't go far enough, and what people really needed was a way to produce real-looking Java classes from Ruby code.

Both of these have been remedied in 1.5, with the addition of several flags:
--java and --javac allow you to generate "real" Java classes from Ruby classes in a given file. You can compile Java code against them, add annotations to them, implement interfaces, reflect their methods, and construct them like normal Java classes.

--handles generates at compile time all "invoker" handles that would have been generated at runtime. This means Ruby scripts can be "completely" precompiled, so that no runtime code generation needs to happen at all.

We also added a --sha1 flag, which produces .class files named based on the SHA1 hash of the actual Ruby source. By using this more standard naming, you can ship .rb files in any directory layout, with .class files somewhere in the classpath, and the association between .rb and .class is maintained.

InfoQ The release notes mentioned a setting 'jruby.jit.codeCache'; are these class files just cached between runs or are they related to AOT functionality?

Both, actually. If you use codeCache=<dir>along with -X+C to force all files to compile on load, you'll see it save off all files that are *actually* loaded during the run. Then ideally you can ship just those classes, rather than precompiling every file in every library (assuming your run touches all files actually needed when the app runs in production. If you use codeCache with normal execution, it will only save off the compiled method bodies that get hot enough to JIT. And if you want to just precompile the lot, you can combine --sha1 and --handles flags to jrubyc with either jarred up class files or codeCache to precompile the lot.

We're going to be putting together some documentation and howtos for all this, but I already blogged a bit about --sha1 and --handles used to precompile Ruby applications for Android.

InfoQ What are the limits of AOT, ie. is it possible to use eval(), metaprogramming, etc?

eval is possible as long as we ship with a parser and interpreter for Ruby code. The only limitation is whether that code will be able to JIT at runtime, which isn't possible in some environments (like Ruboto--JRuby on Android). We are also considering building a stripped-down JRuby runtime that only includes the pieces needed to run precompiled code; in that case, eval wouldn't be possible...but it might be worth it, since it would mean we wouldn't have to ship the parser, interpreter, AST classes, compiler, ASM (for bytecode generation), and potentially more.

If your metaprogramming requires eval, it's subject to the same requirements. But it always works as long as it doesn't require eval. Method and block bodies can be compiled "completely", so it's possible to use define_method and friends even when eval isn't available.

InfoQ What's the status of FFI and other methods for accessing native libraries?

In JRuby 1.5, we switched away from JNA (Java Native Access) and moved to JFFI (Java Foreign Function Interface). Wayne Meissner, our native binding expert, worked extensively on JNA, and he carried that knowledge over to JFFI to make it faster more efficient. All our native library logic, including our binding of POSIX functions not normally available on the JVM (JRuby can work with symlinks, open UNIX sockets, and more), pass through JFFI now, and we ship with JFFI's native bits for all the popular platforms and several weird ones (PPC-AIX! zLinux!).

InfoQ What's the state of to Wayne Meissner's JRuby Native Extension support?

Wayne mocked up an early prototype of a "Ruby C API" for JRuby, with the hope that community members would help us fill it out so we could run at least some of the many native extensions people have written. But working on such a layer is not for everyone, and it didn't move forward in the face of other bugs and features that we deemed more important.
However, there's good news: as part of the Ruby Summer of Code, JRuby will have a dedicated student this summer to help us work on the C extension support. I'm not sure if we'll be able to do enough for *most* extensions to work, but I think we'll be able to provide a safe subset that enables *some* extensions to work. I also hope that by drawing a line in the sand and only implementing the API calls we feel are "safely" implementable, we'll help provide some guidance for C Ruby moving forward.

InfoQ What's the state of 1.9 support?

We did a lot more work on Ruby 1.9 support in this release, and there are users running JRuby in 1.9 mode...but we didn't make a concentrated effort. And this is for a good reason; late last year, The Ruby 1.9.2 manager Yuki Sonoda (yugui) broke with the "Christmas release" tradition by saying that 1.9.2 needed more work and its release would be delayed into 2010. They're now approaching completion of 1.9.2, which means we'll soon have a "stable" version of 1.9 we can begin to chase in earnest. I'd say JRuby 1.6 is the release to watch for more "complete" 1.9 support.

InfoQ What's the state of the MLVM, the Java 7 work, eg. with invoke_dynamic, etc.?

MLVM's most interesting and more mature component, invokedynamic, has mostly undergone lateral changes since this past fall. For example, the APIs have been improved, and the underlying implementation in Hotspot has advanced considerably. We've been tracking those changes and keeping JRuby's invokedynamic support in sync. We've also started to see JRuby+invokedynamic run slightly faster than JRuby on Java 6; That's very promising.

Another interesting development is the work on coroutine support for MLVM (and perhaps eventually for JVM proper). Lukas Stadler posted a blog entry recently where he reworked JRuby's Ruby 1.9 "fibers" support (you might know them as coroutines or threadlets or cooperatively-schedule microthreads) to use the coroutine support he'd worked on for Hotspot. The results were very impressive; JRuby fibers plus Lukas's continuations performed better than the green-threaded implementation in Ruby 1.9, a feat we'd thought impossible. Even better, it eliminated the use of native threads, which is how JRuby on standard JVM simulates coroutines now. I don't know if there's any chance of this getting into a real JVM release, but it would be greatly appreciated by any languages that need coroutines or threadlets.


Lukas Stadler's work on bringing coroutine support to the JVM.

InfoQ Any big plans for 1.6?

We have a few thoughts in mind:
* Continue integrating the rest of the Java platform by adding Maven support to Rake, extension support to jrubyc --java, and many more walkthroughs of using class-based frameworks with JRuby that were difficult or impossible to use before.
* Ruby 1.9.2 support. We've got a lot done, but there's a lot more to do. We definitely could use some community help here.
* A new look at performance in JRuby. We've continued to perform very well compared to the standard Ruby implementations, but there are specific domains where newer implementations like MacRuby and Rubinius easily outperform us. Some of that is due to intrinsic limitations of running on the JVM, like the need for 100% boxed numbers (which severely penalizes us on numeric algorithms). But a lot of it is because we haven't made a major perf push in JRuby since perhaps mid 2008. There's a lot of things we know we can improve...they're just a bit tricky.

InfoQ The JRuby team has written a book on JRuby - what's the target audience?

We have tried to make this book approachable for both Ruby developers interested in using the JVM or Java libraries, and for Java developers looking to move some of their code to Ruby (or some of their web applications to Rails). There's lots of walkthroughs, plenty of beginner-to-intermediate content, and we've got more chapters on the way.

Charles recently blogged about the plans for JRuby performance improvements in future releases.

InfoQ EngineYard now offers commercial JRuby support - any news about this?

Yes! Engine Yard is now offering support + services packages for JRuby users worried about safely investing in JRuby at their organizations. You can get remote customer support, dedicated bug-fixing hours, and even on-site time. We're hoping this will make it easier for large customers to make moves toward JRuby in confidence, and see it as a perfect complement to our top-notch OSS-style support that all users receive (as time permits, of course). 

No comments

Watch Thread Reply

Educational Content

New-age Transactional Systems - Not Your Grandpa's OLTP

John Hugg discusses high volume transaction processing applications with high and low frequency profiles, and how VoltDB can be used for that purpose.

Cool Code

Kevlin Henney examines code samples to see what can be learned from them starting from the premise that one won’t write great code unless he knows how to read it.

Collaboration: At the Extremities of Extreme

Jason Ayers share the observations he made watching a team of developers collaborating in real time on the same code base, pushing XP, pair programming and continuous integration to their extremes.

Yesod Web Framework

Michael Snoyman presents Yesod, a web framework written in Haskell and containing a web server, templating, ORM, libraries (templating, gravatar, etc.).

Transactions without Transactions

Richard Kreuter and Kyle Banker on how to avoid classical RDBMS transactional systems by using compensation mechanisms, transactional messaging or transactional procedures.

Attila Szegedi on JVM and GC Performance Tuning at Twitter

Attila Szegedi talks about performance tuning Java and Scala programs at Twitter: how to approach GC problems, the importance of asynchronous I/O, when to use MySQL/Cassandra/Redis, and much more.

10 tips on how to prevent business value risk

One category of risk that project teams need to ensure they address is business value failure – delivering a product that fails to provide value for the business investor.

Interview: Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives

InfoQ spoke to the authors of Software Systems Architecture on a couple of new topics, the System Context viewpoint and Agile, which have been added to the second edition.