Nibbling Away at Performance
JRuby's performance has never been stellar. Even before the current performance-hindering refactoring and "correctification" work began, it was almost an order of magnitude slower than MRI ("Matz's Ruby Interpreter"). When I started working on my parts of the JRuby internal redesign, I knew thing were going to get worse before they got better...but I think they're finally starting to get better.
I ran some quick numbers comparing performance of JRuby 0.9.0 versus current trunk:
Under 090, gem install rake-0.7.1.gem:
real 1m39.088s
user 1m37.666s
sys 0m1.128s
Under trunk:
real 1m16.388s
user 1m15.233s
sys 0m0.924s
That equates to about a 23% improvement in speed. Considering that we've only been nibbling at performance and that our large-scale performance-related refactoring has just begun, things are looking a lot better than they were six months ago.
The current goal is to get interpreted-mode JRuby as close as possible to MRI performance before we commit to a bytecode compiler. Because the eventual compiler will have to appropriately hook into JRuby's runtime, this only makes sense: if we go full-bore on a compiler now we may see great improvement in performance, but we'll have a much harder time evolving the runtime. By making the interpreter runtime as well-designed and as fast as possible now, we run less of a risk that compilation later on will tie us to a poor runtime design. I believe too many language projects fall into the trap of immediately diving into compilation without first considering how a language should best be represented on the target machine. When we do the hard work of improving the interpreter first, we learn the nuances of the language and gain a better understanding of how that compiler should eventually look. It may even be the case that we find a more direct mapping from the language to the platform that allows us to minimize or eliminate the runtime entirely for compiled code. We'd never reach that conclusion if we prematurely optimized by banking on a compiler too early.
At any rate, things are looking good for JRuby performance, both for small-scale optimizations and large-scale refactorings. The compiler will just make good...better.
I ran some quick numbers comparing performance of JRuby 0.9.0 versus current trunk:
Under 090, gem install rake-0.7.1.gem:
real 1m39.088s
user 1m37.666s
sys 0m1.128s
Under trunk:
real 1m16.388s
user 1m15.233s
sys 0m0.924s
That equates to about a 23% improvement in speed. Considering that we've only been nibbling at performance and that our large-scale performance-related refactoring has just begun, things are looking a lot better than they were six months ago.
The current goal is to get interpreted-mode JRuby as close as possible to MRI performance before we commit to a bytecode compiler. Because the eventual compiler will have to appropriately hook into JRuby's runtime, this only makes sense: if we go full-bore on a compiler now we may see great improvement in performance, but we'll have a much harder time evolving the runtime. By making the interpreter runtime as well-designed and as fast as possible now, we run less of a risk that compilation later on will tie us to a poor runtime design. I believe too many language projects fall into the trap of immediately diving into compilation without first considering how a language should best be represented on the target machine. When we do the hard work of improving the interpreter first, we learn the nuances of the language and gain a better understanding of how that compiler should eventually look. It may even be the case that we find a more direct mapping from the language to the platform that allows us to minimize or eliminate the runtime entirely for compiled code. We'd never reach that conclusion if we prematurely optimized by banking on a compiler too early.
At any rate, things are looking good for JRuby performance, both for small-scale optimizations and large-scale refactorings. The compiler will just make good...better.
Written on August 11, 2006