Wednesday, April 25, 2007

What Would I (Will I?) Change About Ruby

The latest Ruby Blogging Contest hits close to home: What changes would make Ruby into a better language without making it into something that isn't Ruby?

As you might guess, I've got some pretty strong thoughts here. I'm not a heavy Rails user, and I'm not as heavy a Ruby user as I'd like to be. But implementing a Ruby interpreter and now compiler has taught me a few things about what's right and what's wrong with Ruby. I'm not going to complain about performance, whine that the C code is too hard to follow, or even attack C-based extensions. Those may be important issues, but they're all fixable in the long term without breaking anything that works today (or by providing reasonable substitutes). I'm also not going to go into language design ideas...I have mine, you have yours, Matz has his. But my money's on Matz to do the "right thing" with regards to actual language design.

What I'm talking about are a few really important changes to the Ruby runtime, libraries, and ecosystem. Take these as my educated opinions...and don't think too hard about whether I'll be working to change these things in JRuby and in the wider Ruby world.

1. Threading

This more than any other area probably means the most visible changes to Ruby. Ruby currently is green-threaded, as most of you know. JRuby implements native threads mainly because Java uses native threads...we just piggyback off the excellent work of the JVM engineers. And the developing Ruby 1.9, the future successor to the current version 1.8 C implementation, provides something in the middle: native threads with a giant lock, so threads won't run concurrently.

So in general, Ruby is trending toward support for native threads. But there's a problem...some of Ruby's current APIs are impossible to do safely with native threads (and in general, impossible to really do safely with green threads...Ruby just does them anyway). Threading needs to be improved, with support for concurrent execution and removal of operations that prevent that.

Specifically, the following operations and features are inherently unsafe, and are not supported by any mature threaded system:

Thread#kill

Killing one thread from another may leave its locks and resources in an unpredictable state. JRuby currently implements this by setting a kill flag on the target thread and waiting for it to die--basically asking the thread to "please die yourself"--but it's not deterministic and the thread could fail to die.

Thread#raise

Forcing another thread to raise an exception can have the same effect as kill, since the thread may not expect to handle the given exception and may not be able to release locks or tidy up resources. JRuby handles this similar to kill, by setting a field to contain the exception a target thread should "please raise", but again it's not deterministic and there's no way to guarantee the target thread will raise.

Thread#critical=

There is no way to deterministically force true concurrent threads to stop and wait for the the current thread, not to mention the horrendous race conditions that can result when locks are involved. As a result of the many critical problems with critical=, it is already slated to be removed in Ruby 1.9/2.0.
In order for Ruby to survive in a parallel-processing era, unsafe threading operations need to go, and any libraries or apps that depend on them need to find new ways to solve these problems. Sorry folks, these aren't my rules. I understand why people like these features...I like them too. But you can't have your concurrency and eat it too.

2. ObjectSpace

ObjectSpace is Ruby's view into the garbage-collected heap. You can use it to iterate over all objects of a particular type, attach finalizers to any object, look an object up by its object ID, and so on. In Ruby, it's a pretty low-cost heap-walker, able to dig up objects matching particular criteria for you on a whim. It sounds like it might be pretty useful, but it's used by very few libraries...and most of those uses can be implemented in other (potentially more efficient) ways.

JRuby implements ObjectSpace by keeping a separate linked list in memory of weak references to created objects. This means that for every ObjectSpace-aware object that's created, a weakref is added to this list. When the object is collected, the weakref removes itself from the list. Walking all objects of a particular type just involves walking that list. Reconstituting an object ID into the object it references is supported by a separate weak list (again, more memory overhead).

There are no plans currently for ObjectSpace to be removed from Ruby in a future version. But there's a problem...in addition to being pure overhead in JRuby (which you can turn off completely by using the -O flag), ObjectSpace limits evolving development of the Ruby garbage collector, breaks heap and memory transparency, and poses yet more problems for threading.

There are many issues here. First off, the JRuby thing. By having to add ObjectSpace governors for all objects in the system, JRuby pays a very large penalty. We're forced to do this because the JVM (and most other advanced garbage-collecting VMs) does not allow you to traverse in-memory objects nor retrieve the object that is associated with a given ID. In general this is because the JVM does all sorts of wonderful and magical things with objects and memory behind the scenes, and the ability to ask for all objects of a given type or pull an object based on some ID number at any time cripples many of these tricks.

The threading issues are perhaps more important. Imagine if you will a true concurrent VM, with many threads creating objects, maybe one or more threads collecting garbage, and synchronizing all this to guarantee the integrity and efficiency of the heap and garbage collector. There is absolutely no room in this scenario for those multiple threads to request lists of specifically-typed objects at any time, nor to provide an ID and expect its object to be presented to you. These features break encapsulation across threads, they violate security restrictions from thread to thread, and they require whole new levels of locking to ensure that while reading from the heap no other thread produces new objects and no garbage collection occurs. As a result, ObjectSpace harms Ruby by limiting the flexibility of its garbage collecting and threading subsystems, and should be eliminated.

3. $SAFE and tainting

Safe levels are a fairly simple, straightforward way to set a "security level" that governs what operations are possible for a given thread. By setting the safe level to various values, you can limit modification of Object, prevent IO, disallow creation of new methods or classes, and so on. Added to this is the ability to "taint" or "untaint" objects. Tainted objects are considered "unsafe", and so certain security levels will cause errors to be thrown when those objects are passed to safe-only operations.

JRuby has safe level and tainting checks in place, but it's almost assured they're not working correctly. We have never tested them, largely because practically no tests (or perhaps literally no tests) use safe levels or tainting, and we've had *exactly one* bug report relating to safe levels, just a couple weeks ago. And to further kill the possibility of JRuby ever supporting safe levels and tainting correctly, my work tonight to fix some safe level issues revealed that doing so would add a tremendous amount of overhead to almost all critical operations like method creation, module/class mutation, and worst of all, object creation.

At this point, safe levels will probably remain in their current half-implemented state for 1.0, but I think it's almost decided for us that safe levels and tainting will simply not be supported in JRuby. In their place, we'll do two things (which I'd recommend the C implementation consider as well:
  • Recommend that people who really want "safe" environments use an approach like whytheluckystiff's Sandbox, which takes a more JVM-like approach to safety: it runs code in a true sandboxed sub-runtime with only "safe" operations even defined. In other words, not only is it disallowed to load in files or hit the network, it's physically *impossible* to do so. What makes this even better is that Sandbox is already supported in JRuby (gem "javasand") and JRuby out of the box allows a fine granularity of operations to be disabled in new runtimes.
  • Implement safe levels like Java handles security restrictions, which we get to leverage since they're already being checked and enforced at the JVM level. We will not be able to map everything...for obvious reasons, checking tainted strings all the time or limiting class and method creation are unlikely to ever happen, but we can limit those operations that the JVM allows us to limit, like loading remote code, opening sockets, accessing local files, and so on. So it's highly likely JRuby's implementation of safe levels will map to clearly-defined sets of Java security restrictions in the near future.
4. Direction

Ruby is a very free-form community. Matz is the most benevolent dictator I've had the pleasure to work with, and most of the community are true free-thinking artists. It's like the hippie commune of the language world. Peace out, man.

But there's a problem here. Ruby needs guidance beyond VM and language design or the loose meanderings of its more vocal community members. It boils down to a few simple points:
  • Ruby needs a spec. Anyone who believes this isn't true isn't paying attention. Now I'm not talking about a gold-standard legal document signed in blood by Matz and the chief stakeholders of the Ruby community. An officially sponsored, widely supported, and massively publicized community spec would work fine--and probably fit the community and the language better. But something needs to done quickly, since Ruby's "bus number" is dangerously low. A spec is not something to be feared...it's a guarantee that Ruby will live on into the future, that alternative implementations (like JRuby) can't intentionally introduce nasty incompatibilities (or at least, that they'd be easy to discover and easy to document), and perhaps most importantly...that the full glory and beauty of Ruby is published forever for all to see and explore, rather than dangerously trapped in very few minds.
  • Ruby needs a non-profit governing body. I'm not necessarily talking about a council of elders here, I'm just talking about some legal entity to which OSS copyrights can be assigned, donations can be made, and from which projects and initiatives can be funded. Maybe this would be RubyCentral, maybe this would be some other (new) organization...I don't know that. But it would be a great help to the community and Ruby's future if there were some official organization that could act as caretaker for Ruby's future. I'm all set to sign over any JRuby copyrights I have to such an organization, to protect the future of Ruby on the JVM just like the future of the C implementation. How about you?
  • Ruby needs you. Granted, this isn't really a change as such. You probably wouldn't be reading this if Ruby didn't already have you. But the Ruby community is at a big point in its lifetime...at risk of losing its identity, being eclipsed by newer projects, or even slipping deep, deep into the trough of disillusionment. What will prevent that happening is the community showing its strong ties, coming together to support official organizations and official documents, and above all, continuing to pour all our hearts into creating newer and better applications and libraries in Ruby, pushing the boundaries of what people think is possible.

Monday, April 16, 2007

Paving the Road to JRuby 1.0: Performance

Since it looks like Antonio Cangiano is going to delay the next running of the bulls until Ubuntu 7.04 is released, I figured the next JRuby 1.0 update could be about performance.

Performance is such a tricky area for Ruby. Folks outside the Ruby community happily malign its performance, fueled by both FUD and by some truths. Folks within the Ruby community either aren't affected by Ruby's performance (it's "fast enough") or they simply don't care (it's slow, but I still love it too much to leave). A small part of the Ruby community takes what is in my opinion a rather anti-Ruby stance: "write it in C" as a targeted solution for identified bottlenecks. I suppose reality lies somewhere inbetween all these views, with Ruby's performance certainly not being stellar in the general case, but reasonable and sometimes surprisingly good for specific cases.

Ruby 1.9 has raised the promise of a new bytecode-based interpreter engine--a Ruby "virtual machine" by some reckonings--with the goal of improving performance foremost on the minds of Ruby's developers. And again the performance question is rather complicated. Antonio's recent shootout, running only Ruby 1.9's chosen benchmarks against all other implementations, shows it doing extremely well. It comes out many times faster than Ruby 1.8 in almost every test, and no other implementation even comes close. The truth however doesn't change very much; for non-synthetic benchmarks (like running Rails) the situation only improves by about 15% for some tests, and for many other tests performance actually degrades. Of course Ruby 1.9 is still under heavy development, and many more improvements are ahead, but the wide range of results demonstrates again that benchmarking must be taken with a grain of salt.

Et tu, JRuby?

So then there's us and JRuby. JRuby's professed goal has never been to be a better Ruby; at best, we're trying to build the best Ruby possible on top of what we believe is the best VM in existence. And toward that end we've put most of our time into compatibility and correctness above all else, aiming for the goal of complete Ruby language compatibility and near-complete builtin-class compatibility, hoping for JRuby to someday be treated as "just another Ruby implementation" on which people can run their apps and design their clever frameworks and libraries. But in the past year, it's become apparent that we could actually exceed Ruby's performance for specific cases in the near term, and for general cases over time. So the target market for JRuby seems to be changing from "Ruby users that must use Java VMs, libraries, and servers" to "Ruby users that want a better-performing, more scalable implementation". And our noble quest for near-complete compatibility gets muddled with all these fiddly performance details.

But that's life, right? The goals you set out for yourself and your projects rarely align perfectly with the goals others set out for you. The trick is achieving a balance between what you want to do with your life and what others (like your community members or your employers) want you to do. Perhaps the successful developer is the one who can derive pleasure from both tasks.

On the road to JRuby 1.0, we've done our best to balance compatibility and performance. We are now nearing the end of the compatibility road, with Ruby language features nearly 100% and builtin classes almost as complete as we can make them on the JVM. The real reason for a JRuby 1.0 now is that we believe we're finally approaching "Ruby compatibility" for some high measure of compatibility, such that the vast majority of platform-agnostic Ruby code should run successfully on JRuby. And that's certainly no small feat, given that just a year ago we celebrated a mostly-broken cobbled-together Rails 1.1 app slowly handling CRUD operations. Today, people are deploying JRuby on Rails apps in production, and the game has only gotten more interesting.

So then, performance. You're all wondering what the answer is to this performance thing, aren't you? Is JRuby going to blow away all competition, including the nascent Ruby 1.9 and mid-term projects like XRuby, Rubinius, and Ruby.NET? It's certainly possible, but it's not our goal. Is JRuby going to be faster than Ruby 1.8 when 1.0 is released? For specific cases, I'd say yes...there's plenty of areas we already perform better than Ruby 1.8. For the general cases, it's hard to say. We perform well serving up Rails requests today, but only about 50-70% of Ruby 1.8's performance. And though we know where most of the bottlenecks lie, we're a little resource limited trying to fix them. Do we believe that we'll be faster than Ruby 1.8 in all general cases in the near future? Yes, we strongly believe that will happen.

Now of course I could ramble on and on about performance and put you all to sleep, but actual numbers will probably keep your interest better than my droning.

The Test

Like the shootout, I'm just running the Ruby 1.9 benchmarks here. We have not done any targeted optimization for these tests; there's no Fixnum magic or anything like that under the covers. What we have done is implement multiple general-purpose optimizations to speed method and block invocation, object creation, and interpretation. We've also spent a little more time getting these tests to compile successfully, but of course any work done on the compiler is generally applicable as well.

These results are all based on JRuby trunk code, revision 3480. I'm running Java 6 on a MacBook Pro 2.16GHz Core Duo, and all code was compiled to target Java 6.

For the first set of results the JRuby command executed basically amounts to the following:

JAVA_OPTS=-Xverify:none jruby SERVER -O [script.rb]
  • JAVA_OPTS=-Xverify:none specifies not to verify classes on startup; this is a large part of the speed hit Java applications have when starting. We turn it off here to remove a little of that overhead from the benchmarks, since most of them are very short runs to begin with.
  • SERVER specifies that JRuby should use the "server" VM, which takes a bit longer to optimize a bit more heavily when JITting Java code into native instructions. JRuby generally performs best under the server VM, though using it impacts startup time.
  • -O disables ObjectSpace in JRuby. This may seem like cheating, but the truth is that when ObjectSpace is enabled we pay double or triple the object creation cost in JRuby since we have to track all objects separately. Ruby's ObjectSpace is essentially zero-cost...it's just a window into the memory manager. Since we don't have a low or zero-cost way to implement ObjectSpace, it falls into what I categorize as "optional incompatibility". If you don't need it, turn it off and JRuby performance will improve. You can call it cheating if you like...the truth is that practically no code actually depends on ObjectSpace.
And then there's the standard disclaimer for any Java application: these times include startup, about 1.0 to 1.3 seconds. I know you all are picky about how benchmarks are run, and you love to include startup time even though the vast majority of the world's work is not done in the first few seconds of execution, but if you'll forgive the disabling of ObjectSpace I'm willing to meet you half way. Startup time is included.
TEST                    MRI     JRuby
--------------------------------------
app_answer 0.584 2.239
app_factorial ERROR 4.248
app_fib 7.126 10.549
app_mandelbrot 2.346 10.300
app_raise 2.587 4.441
app_strconcat 1.829 2.141
app_tak 9.711 13.345
app_tarai 7.529 11.050
loop_times 5.475 6.903
loop_whileloop 9.982 11.797
loop_whileloop2 2.009 3.292
so_ackermann 13.726 26.132
so_array 7.257 8.801
so_concatenate 2.063 3.546
so_count_words 0.507 4.491
so_exception 4.342 8.346
so_lists 1.238 2.744
so_matrix 2.258 4.241
so_nested_loop 5.609 7.898
so_object 7.050 6.496
so_random 2.139 4.643
so_sieve 0.740 2.240
vm1_block 23.604 27.405
vm1_const 16.774 20.650
vm1_ensure 16.546 15.800
vm1_length 21.210 21.899
vm1_rescue 13.170 16.197
vm1_simplereturn 21.091 31.376
vm1_swap 25.114 17.949
vm2_array 6.049 5.690
vm2_method 13.528 17.759
vm2_poly_method 16.886 24.956
vm2_poly_method_ov 4.576 6.972
vm2_proc 7.060 7.797
vm2_regexp 4.421 9.353
vm2_send 4.332 8.198
vm2_super 4.992 7.944
vm2_unif1 3.838 6.095
vm2_zsuper 5.409 8.452
vm3_thread_create_join 0.019 1.592
Some of these are rather surprising results. This is JRuby running in plain old interpreted mode, with no compilation involved. The majority of the tests still have JRuby slower than Ruby 1.8, but the gap has narrowed an incredible amount since last year. In only a few tests are we more than twice as slow as MRI, and on a couple we're almost twice as fast. If you'll imagine startup time removed from these numbers, and believe me when I say Java takes far more than 30-60 seconds to rev up to full speed, then the situation looks even better. What's more, we've got a good several weeks before the first 1.0ish release is scheduled (something betaish or RCish that proudly proclaims it's "done") and a bunch of great committers and community members eyeing performance metrics.

Ok, you may be asking "what about JRuby's compiler?" Yes, there is a compiler in the works. It's primarily been my job to build out the compiler, though Ola has jumped in a few times to offer his excellent help. And progress has been slow but steady. You have to remember that in all the world, there's no known 100% complete Ruby compiler for a general-purpose VM. There's Ruby 1.9, but its bytecodes have been custom designed around Ruby. There's XRuby and Ruby.NET, but it's still unclear how complete they really are. So this is an open area of research and development. But the results are looking great so far.

For this test, both the ahead-of-time (AOT) compiler and the just-in-time (JIT) compiler modes are activated. This forces the target script to be compiled before execution and also compiles any methods hit heavily once execution gets going. The command amounts to the following:
JAVA_OPTS="-Djruby.jit.enabled=true -Xverify:none" /
jruby SERVER -O -C [script.rb]
  • -Djruby.jit.enabled=true enables the JIT compiler. The default threshold at which a (compilable) method gets compiled is 50 invocations.
  • -C tells JRuby to compile the target script before executing it. If the script can't be compiled, JRuby bombs out with an error.
The compiler can't handle all the Ruby 1.9 tests yet. Specifically, it doesn't handle multiple assignment (e.g. vm1_swap), exception handling (anything involving rescue or ensure), or full class definitions. But it compiles the majority of the tests.
TEST                    MRI     JRuby
--------------------------------------
app_factorial 0.029 3.459
app_fib 7.094 5.093
app_mandelbrot 2.340 9.011
app_strconcat 1.827 2.391
app_tak 9.714 5.394
app_tarai 7.515 4.642
loop_times 5.428 2.942
loop_whileloop 10.016 6.027
loop_whileloop2 2.012 2.191
so_ackermann 13.610 11.254
so_concatenate 2.043 2.396
so_lists 1.250 2.141
so_matrix 2.256 2.394
so_nested_loop 5.614 4.167
so_random 2.158 3.291
so_sieve 0.741 1.798
vm1_block 23.392 12.397
vm1_const 16.980 8.908
vm1_length 21.094 10.901
vm1_simplereturn 21.252 9.345
vm2_array 6.025 3.041
vm2_method 13.049 7.794
vm2_regexp 4.468 7.647
vm2_unif1 3.855 3.293
vm3_thread_create_join 0.017 1.389
Ahh, now things look a bit different! In almost every case, JRuby performs better than Ruby 1.8. In the long running cases, the difference is even more obvious. Short runs still put Ruby 1.8 ahead, but I'm totally ok with that. Java, and by extension JRuby, has never had stellar short-run and startup performance. But we don't really have to if the heavy, long-running apps people actually use end up running faster.

Note also that this is the first real compiler we've had; it's not doing any optimization like Ruby 1.9's and Rhino's compilers, and it's almost certainly far from being efficient. I'm no compiler expert, and this is my first real attempt. These numbers already looking so good demonstrates that there's a grand adventure ahead of us: Ruby really can be made to perform well on the JVM. It just requires a little confidence and a little more effort.

That pretty much wraps up this installment. The bottom line: As we approach JRuby 1.0, our performance is better than it's ever been--faster than Ruby 1.8 for many specific cases, with stellar across-the-board performance right around the corner. And with other implementations like Ruby 1.9, XRuby, Rubinius, and Ruby.NET rapidly coming of age, Ruby's future is looking extremely solid.

script type="text/ruby"

Remember way back when the IRB applet was first thrust upon the world, and I promised that you truly could now use Ruby in the browser? At the time, it was still a little cumbersome, and generally you could only use Ruby by passing it directly into the applet.

Well Dion Almaer has taken it to the next awesome step:

<script type="text/ruby">

Check out his blog entry on how to enable true Ruby scripting on the client side, as well as the link to his demo page (still loads up the applet in the background, but that's a minor implementation detail).

Awesome.

Friday, April 06, 2007

Paving the Road to JRuby 1.0: Unicode

Well friends, the countdown has begun. Within the next several weeks, we're looking at getting a 1.0 release out in either beta or RC form. Of course most of you OSS folks know how arbitrary release numbers are...the day after we branch 1.0 we're going to start committing to 1.1, and the cycle will continue. But it seems like the last year is coming to a very solid milestone, and these stabilization points are necessary once in a while. So it comes to pass.

As part of "closing the door" on 1.0, we're weighing features and bugs and wishes to decide what makes the cut and what must wait for a future release. To help get the word out, I'll be doing a series of entries on where we are, where we'll be for 1.0, and where we're going in the future. First off, one of the biggest issues for Ruby--Unicode support--and what it will look like in JRuby 1.0.

Unicode

Straddling two worlds is complicated. Ruby is dynamically typed, with open classes, redefinable methods, eval...a very different sort of world than Java. If those really obvious items weren't tricky enough, Ruby has another wrench to throw into the works: it cares not for Unicode.

Of all issues, this is probably the most problematic to solve. Java, as you know, is always unicode, representing strings internally as UTF-16 and supporting most external encodings you could ever possibly want. Ruby, on the other hand, pays little attention to encodings most of the time, preferring to just treat strings as an array of bytes. If it's encoded, so be it. If not, so be it. The majority of Ruby's string operations work with bytes (though there are a few smart exceptions), so multibyte-encoded strings can be damaged if you have high expectations.

We've spent the past year weighing options. We want JRuby to be compatible with the C implementation, since it's widely deployed and apps depend on its sometimes quirky string behavior. We also want JRuby to integrate well with Java, and the boundary to be as seamless as possible. How does one accomplish that? We've gone through a couple options:

  • At first, JRuby's string was represented with a String/StringBuffer internally. This allowed the original JRuby authors the most trivial path to a fully-working string implementation; almost all the heavy lifting was done for them, and for simple cases it worked fine. But the APIs did not conform to what Ruby applications expected, frequently returning 16 bit values for individual characters and reporting incorrect byte lengths for strings that couldn't encode into all 8-bit characters. It was broken, as far as Ruby code was concerned.
  • The second option, which is what we currently have, is to do what Ruby does...treat all strings as byte[], and implement all operations to the letter of the law. This allows us to make even the lowest-level APIs conform exactly, and to be honest that's been necessary to get applications like Rails up and running. Ruby blurs the distinction between a byte[] and a string so completely that Rails actually now ships with its own multibyte helper, a library that stands a good chance of becoming widely deployed. So to support Ruby and all its many wonderful apps, we fell in line.
At this point it's appropriate to answer a question many of you may have: If JRuby's strings are to be byte[]-based, how can you integrate with Java? A few answers have been proposed. The one I put forward some months ago was that we should treat Java strings like any other Java object, allowing developers to explicitly work with either Java strings or Ruby strings--never the twain meeting without full consent of both parties (or perhaps by using a few helper APIs). This allows Ruby's strings to work as you'd expect, and Java's strings to work as you'd expect, but it doesn't get the nicest flowthrough we really want in this case. So then there's a compromise option likely to be "it" for 1.0.

When crossing the boundary, Ruby will be assumed to use UTF-8 strings.

There are many benefits to this even beyond the fact that it took me 15 minutes to make it work. It allows Ruby strings to behave like Ruby apps expect them to. It allows Java strings to pass into and out of Ruby code without corruption. And it allows Ruby strings to pass into Java code with the only prerequisite (if you want to avoid garbled strings) being that they should be decodable UTF-8. That last item seems like a fairly reasonable requirement given that you're calling 100% unicode Java APIs, and in general the people that will care about this conversion are the ones already using unicode.

Of course, nobody calling these APIs would ever see this or have to do anything special...strings will pass back and forth and encode/decode as necessary, and things will generally just work. And there are performance tricks we can use to speed things up if that becomes a real issue. But it also does something no other proposed solution can: it solves the problem pretty darn well...in time for 1.0.

So for the record, this is the proposed solution we'll go with in the 1.0 timeframe:
  • Ruby strings are byte[] and conform to Ruby string semantics
  • Java strings passing into Ruby code will be encoded as UTF-8, with the implication that you should expect to be working with UTF-8 byte[] in the receiving code
  • Ruby strings passing out of Ruby into Java libraries will be assumed to be UTF-8, and the resulting string on the Java side of the call will reflect that assumption.
And what does the future hold? Well, there's a number of exciting areas happening post 1.0:
  • At some point, either before 1.0 or immediately after, there will be an installable gem that provides Java-native support for Rails' MultiByte library, which should provide a substantial performance boost there. As it is, the current pure Ruby version works almost 100%, so the extra performance should ultimately just be a bonus.
  • We will start implementing a Ruby 2.0-compatible string, but it's unclear when would be a good time to flip that switch. I would predict that JRuby users will have a choice of which to use fairly soon, and we'll swap out behavior depending on what you want.
  • It's also likely that we'll present clean ways to "just use Java strings" for developers that want to do that. This would not result in code that's compatible with stock Ruby, since we'd obviously have to "unicodify" many Ruby methods, but it fits into a larger goal of Ruby-enabling the Java platform as well as possible
  • And of course, some combination of these three and the current solution is possible, given some time and thought. Ultimately it will be driven by you, the users of JRuby, and what you want to see done with it. Because that's what we here at Sun are trying to be all about...what users and developers want to be doing.
So that about wraps up the unicode story for 1.0. I believe it's an excellent compromise between full Ruby compatibility and tight integration with the Java platform, and it gets us where we need to be right now. So what do you think?

Saturday, March 31, 2007

ActiveRecord 100%, Performance Doubling, Java Support Improving

I haven't blogged a solid JRuby update recently...and this one isn't going to be as solid as I'd like, but it should let you all know that the wheels are still moving and the train is picking up speed. It's astounding how much progress is being made.

ActiveRecord Now Fully Supported

It's good to have such incredible community members and great core team members.

Ola Bini, who recently accepted an offer from ThoughtWorks, has been hitting Rails unit tests hard. And the module with the most failures has always been ActiveRecord. It's the most complicated and the weakest point in the JRuby on Rails story.

Until now.

1031 tests, 3839 assertions, 0 failures, 0 errors
That headline should read "ActiveRecord Fully Supported on JRuby", for you press affiliates out there.

Of course there's a few caveats, but they're pretty minor in this case. That's zero failures and zero errors when running against MySQL, but it's certainly a de-facto standard in the Rails world. The next step is to get as many other databases to 0/0 as possible. And those are much smaller steps than this first one.

So what does this mean for JRuby on Rails users? Well in general, it means that the heart of your DB-driven JRoR apps--ActiveRecord--is now the best-supported piece of the puzzle. It also means that overall Rails support is well into the 99% range and still climbing.

Performance Continuing to Improve

In addition to the focus on getting Rails working well (which is really a focus on improving overall Ruby compatibility) we've been hitting performance much harder the past couple weeks. I especially have been splitting my time between interpreter and compiler work. As a result of all our efforts, the current trunk code is almost another 2X the performance of 0.9.8, released less than a month ago. The compiler also supports almost 2X the number of syntactic constructs it did in 0.9.8, and it's getting faster and more stable every day.

There are actually a number of benchmarks running faster than MRI (the C version of Ruby) even when interpreted, showing that we're finally making good on our promise to have interpreted JRuby run as fast as MRI. So it truly does seem that the compiler will be "bonus" performance once we work out the remaining bottlenecks in the system.

Java Support Looking and Feeling Better

There have been two areas of focus for Java support the past few months: rounding out features and syntax and improving performance. Both had some great jumps in JRuby 0.9.8, with a couple small fixes improving performance many times and with concrete/abstract class extension finally making it into a release.

Since 0.9.8 we've continued to make progress on both fronts. I've made a few additional small changes to improve overall performance, and Ola's been moving some especially critical pieces of code into Java, since they represented a lot of back-and-forth across that barrier. Where calling into Java code was previously as bad as twenty times slower than calling Ruby code, it's now a modest two times slower. We expect to improve that further, getting as close to Ruby invocation speed as possible.

We've also just added what should hopefully be the final revision to our various "import" syntaxes. Oddly enough, we've come full circle to "import":

# create a new constant "System" pointing at it
import java.lang.System

# use Java::syntax for less-common packages
import Java::my.weird.package.MyClass
And we're considering some improvements to how multiple classes are imported and how to specify an alternate constant name (for classes like String, which would be a bad idea to overwrite).

You can expect to see this all solidifying as we run these last miles toward JRuby 1.0.

--

I will blog more on all this as we get into April, but it's truly shaping up to be Springtime for JRuby in JavaLand.

Friday, March 30, 2007

Can Your Ruby Do This?

# scripting.rb

include Scriptable

x = 'Hello'
y = 'world'

groovy <<G
def z = 'multilanguage'
println("${x}, ${z} ${y}")
G


javascript <<JS
z = 'multilanguage'
println(x + ', ' + z + ' ' + y)
JS


# both => "Hello, multilanguage world!"

Saturday, March 10, 2007

Ruby on Grails? Why the hell not?

I've spent some time this weekend looking over the Grails codebase. After a truly gigantic checkout (Grails bundles production JARs for all the libraries it integrates) and after swimming through a substantial, single-project sea of source files, I think I'm starting to follow it (though a tour by someone familiar with Grails internals would be nice). But there's something else I've learned in the process...

There's really no reason this couldn't use Ruby just as easily as Groovy.

Let's look at some really dumb numbers. Grails, as it turns out, is actually over 2/3 Java code, unlike Rails which is 100% Ruby. Grails contains around 436 Java source files for about 54kloc of code and 273 Groovy source files for about 23kloc of code. So Java outnumbers Groovy by a 2:1 ratio. And yes, Java's probably more verbose than Groovy in most cases. But my point stands, and I'll back it up with more...

Then there's the libraries. The Grails binary release weighs in at a whopping 26MB compressed and 49MB uncompressed (*wow*). But 31MB of that is third-party libraries completely independent of Groovy, things like Hibernate, XFire, Quartz, Apache Commons, and so on. Almost all of which (or perhaps all of which) are pure Java code. So the ratio is even more heavily toward Java.

These numbers and my exploration of the code base lead me to a surprising conclusion: Grails is not a "Groovy on Rails" by any means. It's a large number of popular, well-established Java libraries stitched together mostly by Java code with a thin layer at the front (20kloc is not much) of Groovy code for end-users to see and work with. And I guarantee you it's not the Groovy part that's most interesting here. Hell, you could write that part in Java if you followed enough "convention over configuration", and you certainly could write it in Ruby.

I decided to do this exploration after realizing there's nothing about Ruby or JRuby that couldn't be used to wire a bunch of Java libraries together--indeed, that's one of the biggest selling points of JRuby, the fact that you can write plain old Ruby code but call Java libraries almost seamlessly (with day-by-day improving integration points and performance numbers). So why not take Grails and do a port to Ruby? Groovy code isn't far off from Ruby in many ways, and everything you can do in Groovy you can do in Ruby (plus more), so the port should be pretty straightforward, right?

Then I find out that Grails is mostly Java code. And instead of being annoyed or repulsed by this revelation, I was intrigued. Why not make Grails work with Ruby as well? And really, why not make it work with any scripting language? Why limit that nicely-integrated back end by forcing everyone to use Groovy, regardless of preference? Have we learned nothing from a decade of "100% Pure Java"?

So I propose the following.

  • I believe it would be possible to completely isolate Grails' tastier bits from Groovy. I don't claim it would be easy, but Grails is fairly well interfacified, injectificated, and abstractilicious, so making that dividing line clear and bold is certainly possible (and heck, that's the point of dependency injection and component frameworks anyway, isn't it?). Really, I could start implementing a few of those interfaces right now with Ruby code, but that's not the right approach.
  • Grails' value is not in Groovy, but in the clean integration of established libraries behind the "Convention Over Configuration" mantra. There's nothing specifically Groovy (or Ruby) about that religion, and there's nothing Groovy does in Grails that another JVM language couldn't do just as easily. This is *truth*. And Grails would benefit tremendously by expanding to other languages. Being tied to Groovy alone will hold it back (just as a framework tied to any one language will be held back, Ruby included).
  • I also believe that if the Grails project doesn't make an official effort in this direction, others are likely to take up that mantle themselves. Though the debates will forever rage about which JVM dynlang should carry us into the future, the same facts that have guided programming for half a century still apply today: No one language will be enough to carry us forward; no languages will survive indefinitely; and the language you'll use in ten years you've probably not even heard of yet. Did anyone expect Java to be the most widely-used, widely-deployed language ten years ago? Well today, it is. It won't always be.
  • There's also a very interesting angle here for language enthusiasts. Nobody doubts that the Java platform is officially becoming multi-lingual, possibly a complete reversal from years past. But there are going to be growing pains here, and we're already feeling them on some projects at Sun. We have this wonderful platform with all these wonderful languages...and they all do things differently. We have a first stab at official "Scripting" support in JSR-223, but it only defines the integration point from Java to the language in question...only partially defining the integration points for those languages calling back to Java (a tricky problem) and defining *nothing* related to making those languages interoperate with each other. Again, Java becomes the integration point, and the bottleneck (as in "how do you pass a dynamic-typed object from one language to another by sending it through a statically typed language?"). The very exercise of making Grails (or any other framework) work equally well across multiple user-facing language interfaces will require better interoperability and more clearly-defined integration points for dynamic and static languages on the JVM.
  • The Phobos guys at Sun are already tackling many of these same problems while expanding their JavaScript-mostly Rails-inspired web framework to other JSR-223 languages (notably, Ruby). So anyone taking on the Grails effort would certainly not be alone, and there are some damn smart engineers at Sun interested in tackling these very same problems.
And I guess in the end it's a question of how visionary we all can be. Can the Grails team envision a future for Grails that doesn't require the use of Groovy? Are you (and am I) as a non-Groovy developer willing to help them get there? And in the end, isn't this what thought leaders on a multi-lingual platform are supposed to be doing?

--

So, enough of the inflammatory bull-baiting. I dare you to tell me why I'm wrong here. Even better, I dare you to look into it yourself. 75kloc of code, only a third of it Groovy. Established libraries you're sure to have used at some point. Clean integration, following the principals inspired and proven by Rails.

But fronted with your language of choice.

Make it so.

Tuesday, March 06, 2007

NetBeans 6 Ruby Support Even Better Than Expected

See, here's the deal. I'm not a very advanced IDE user. I used Eclipse for years and JDE before that, and I wouldn't ever have considered myself a "pro" with either. I learned what I needed to get the job done and not a whole lot else. Beyond that I never knew some of the coolest features, and was never so good at convincing people to make a switch. This actually has helped my migration to NetBeans, since it basically does all the things I was used to in Eclipse. But it has been problematic when I try to convey how cool the new NetBeans Ruby support really is.

It's super cool. It does things I've not seen any other IDE or editor do.

However, it's best not to take my advice, and Roumen Strobl has recorded two seriously excellent demonstrations of Rails and Ruby support in NetBeans. They make the sale way better than I could (though I now have many good ideas for how to sell it better in the future).

If you have any interest in Ruby editors or IDEs, you should take the time and watch these, especially the Ruby support.

Two Demos: JRuby on Rails and Advanced Ruby Editing in NetBeans!

Behind The Scenes: JRuby 0.9.8 Released!

Things have been moving quickly in JRuby-land, and we've just kicked out a major release in JRuby 0.9.8. Among the big features:

  • Ruby classes can extend concrete/abstract Java classes and override methods
  • New Java primitive array syntax
  • Reimplementation of String, Numeric classes, and Array to be more correct and performant
  • Significant bottlenecks have been identified. In some cases IO is 6.5x faster than previous releases. Java included classes are significantly faster than in the past.
  • 220 Jira issues resolved since last release
Now these are certainly delicious. Performance improvements are always great, and we're been improving Java integration little by little. But there's another bullet I omitted that is worth a little more attention:
  • Ruby on Rails support
Now you may feel free to read that as you wish. I read it as "we expect pure-Ruby Rails apps to work." By "pure Ruby", I mean no unsupported C-language extensions required. By "work" I mean "work."

It was our original plan over two months ago that by Februrary's end we'd be passing enough of Rails' own test cases to call it "supported". And in a relative rarity for an open source project, we hit that milestone. It was actually early last week we started saying we officially support Rails, which at the time meant better than 95% of Rails test cases passing. By the time we cleaned up the remaining release items, we had passed 98%. And we're still climbing.

So what does this mean for a practical Rails user? Well, it means that the dream of deploying Rails apps on any Java-based server in any Java-based organization is another big step closer to coming true. I've actually been demoing Rails apps running in a WAR file on GlassFish for all my recent talks, and it's pretty solid. I don't imagine it's perfect, of course, but it's looking really very good. It will be "ready" by the time we hit 1.0.

A few folks have been wondering about the jump from JRuby 0.9.2 to JRuby 0.9.8. The simple answer is this: we're two releases away from 1.0. We wanted to make it obvious how much work has gone into 0.9.8 (as many SVN revisions in this release as the last three combined) and show our commitment to getting a 1.0 release out very soon. The 0.9.8 release will be followed by 0.9.9, which will be followed by...well, you get the picture. We're in the home stretch now.

The other core team members have reported on the release, so I won't cover all that. Here's a list of links:

Tom Enebo
Ola Bini
Nick Sieger

In related news, there's also a new release of ActiveRecord-JDBC, the gem-installable module enabling JDBC databases to be used by ActiveRecord. This is also very welcome, since there have been a number of bug fixes in trunk that weren't easily installable the past couple months. Now you should be able to run both Rails 1.2.2 and 1.1.6 well with JRuby, just using released code. It helps complete the puzzle.

So what's next for JRuby? Well, with the 0.9.8 release we've reached a really big milestone as far as Ruby compatibility, so we're likely to turn our attentions toward areas not directly related to Ruby 1.8. Specifically:
  • Work will continue on the bytecode compiler, and I'm hoping to have the JIT permanently enabled within the next week
  • Java integration will get a heavier focus, to start bringing us more in line with languages like Groovy for ease-of-integration. In general things are looking pretty solid right now, but we know there's a lot of work to do here. I'd like for us to come as close as possible to Groovy's level of tight integration as possible.
  • We will also start working on native Unicode support, by exposing a Chars class like the one provided in Rails' MultiByte library. This will allow us to maintain compatibility with Ruby and provide solid Unicode support without introducing an incompatible set of features.
  • Both Tom and Ola have expressed an interest in continuing work on our Ruby 2.0 bytecode engine. Ola would like to continue improving and expanding the bytecode support, while Tom would like to play with a second parser that goes straight to bytecode. Both of those will help feed into a potentially faster interpreted mode in the future, giving us many of the perf gains shown in Ruby 1.9 benchmarks.
For me personally, performance is going to be the big item. The recent Ruby Shootout showed that we have some work to do to bring out performance up to MRI standards, but it didn't tell the whole story. The truth of the matter is more like this:
  • JRuby interpreted mode is roughly 3-4x as slow as Ruby 1.8
  • JRuby compiled mode is roughly 1.5-2x faster than Ruby 1.8
  • KRI (Ruby 1.9, "Koichi's Ruby Implementation") is many times faster than MRI for the posted benchmarks
  • KRI is 2x or less faster than MRI for the general case
And this is without us doing any optimization of the compiler or adding in any special-case optimizations like KRI provides for fixnums. We're still looking great for future performance, and I want to start tackling this area heavily over the next couple months.

As always, we welcome contributors, bug reports, patches, and user anecdotes for JRuby. We love to hear about bugs, we want to know your opinion, and we respect and honor our community whenever we get the chance. Remember, JRuby is your project, and can only be successful with your help.

Visit www.jruby.org to learn more about the project, download the release, and get involved!

On to the next release!

Thursday, March 01, 2007

JRuby World Tour: Bangalore

After my adventures in Hyderabad, the next stop on the tour took me to the heart of India's IT industry, where I would present my TechDays talk again for Sun Microsystems' Indian Engineering Center. But I scheduled in a little free time as well, to do some exploring.

I arrived on Saturday the 24th after a short flight on Sahara Air. For once, my travel arrangements worked out, and I was able to buy my ticket upon arriving at the Hyderabad airport. A few hours later, I had landed in Bangalore. A hotel car was waiting for me (this is now only the second time I've had a car waiting with my name on a sign, and I think I like it), so I headed straightaway to the Richmond Hotel in central Bangalore.

The Richmond has a fairly old-world feel, apparently having been converted from an apartment or office building some time in the past. It had a musty smell, but was otherwise pretty clean and well-kept. I'm generally more comfortable in "clean and comfortable" hotels than in "pristine" hotels like the Novotel, so the Richmond was just fine. That night I made arrangements for the next day's tour, ordered in some room service, and caught up on sleep.

It still amazes me how everything has changed since blogging became mainstream. Even as short as five years ago, I had a devil of a time finding local tour guides for my travels. Generally the best bet was to fork over too much money to a paid guide or to travel with a tour group. Neither of those are really conducive to free-form exploration, so I've always been forced to strike out on my own. But those days are certainly behind us.

In response to my "World Tour" blog posts, I had no less than 5 different people offer to show me around Bangalore. They ranged from JRuby enthusiasts to casual readers, and for once I had more guide offers than I could use. So I settled on the first two to contact me: K "Venkat" Venkatsubramaniyan and Håkan Raberg.

Venkat was up first on Sunday the 25th. He had actually stopped into the JRuby IRC channel (#jruby on FreeNode) as well as emailing me. His plan for the day included a trip to a cultural/folk center outside the city, lunch and dinner at a couple places to be determined, and shopping stops for a few things I wanted to purchase. So we started out bright and early at 9AM.

We made the following stops, in order:

  • Rajarajeshwari Temple in western Bangalore, where I paid my respects and was gifted with a wreath of flowers and a tilak on my forehead. It was a moving experience, even though I felt a bit out of place in my western clothes. And the classical architecture of this modern shrine was quite impressive.
  • Janapada Loka (Folk-Cultural World), a collection of folk art museums and exihibits on the road from Bangalore to Mysore.
  • Kamath Yathrinivas Restaurant, where I had my first traditional Indian meal, complete with banana-leaf plate and eating with my hands. It was very tasty.
  • Nalli Silk Arcade, to purchase sarees for my wife. I think I was the only guy in there shopping, other than a few poor saps who were obviously dragged along by their wives.
  • Cauvery Crafts Emporium on Mahatma Ghandi Road, a nice collection of handicrafts, clothes, and nick-nacks, but very much tailored to western tourists. I looked at pearls for my wife briefly here, but decided not to buy.
  • Navaratna Jeweleries, up the road from Cauvery, where I found the pearls I wanted. I went back on Tuesday before flying home to have the string extended and a clasp put on.
  • Garuda Mall and Bangalore Central Mall...we just kinda ended up here looking for a place to buy tea and wasting time before our evening's restaurant opened.
  • Amaravathi Restaurant, another more traditional place (more banana leaves and eating with hands), but this time with some delicious spicy curries and a crab dish as tasty as it was difficult to eat.
Venkat was an excellent guide, and I can certainly claim a new friend in Bangalore.

Monday the 26th was my day on the spot at Sun Microsystems. Conveniently, Sun's office in Bangalore was only about two blocks from the Richmond, so I headed over at around 10AM to prepare for my 11AM talk.

For some reason, every Sun office I visit is a terrific maze of doors, offices, and cubicals. The Menlo Park office has all L-shaped buildings with multiple intersecting hallways. Santa Clara's offices are plus-shaped (I think) which is often even more confusing. The Bangalore office put them to shame. It is hosted on the 4th, 5th, 6th, and 7th floors of a circular building with a central unsecured walkway and multiple secure entries and exits as you progress around the outer ring of offices. What complicated things most was that hallways extended out from the center of the ring like spokes of a wheel, but the perpendicular hallways did not always curve to match the circle. This meant that hallways often met at bizarre angles, and it was impossible to maintain any sense of direction. I got lost more than once wandering around, and unlike the California offices, I had no guarantee that following a given hallway would eventually lead me to an outside wall. Bizarre.

Anyway, I did the same talk from TechDays for Sun folks from 11AM to 12PM. Unfortunately, I had lost favor with the demo gods. My NetBeans demonstration froze up and refused to come back. My Rails demo failed with an error I still haven't isolated. And because of a peculiar scheduling snafu, the last 15 minutes of my talk had to be condensed into five minutes, resulting in more errors and a very flustered presentation. What had gone perfectly a few days earlier at TechDays went very poorly at Sun. Luckily, it seems to have still been well-received, and the classic JIRB demo was enough to wow the crowd.

The rest of the day was spent meeting with various folks at the IEC, talking about their projects and how JRuby could help. There's some cool stuff coming out of Sun India, so keep your eyes and ears open over the next few months.

Monday night my new friend Hakan Raberg from ThoughtWorks arranged to meet with me and two other ThoughtWorkers for dinner. It turns out Hakan is an old friend of Anders Bengsston, one of the premier JRuby contributors in the old days before I joined the project. Such a small world.

As a nice change of pace, the ThoughtWorkers and I had dinner at Barbeque Nation, a trendy, modern-feeling restaurant featuring fairly traditional northern Indian cuisine. In other words, lots of meat. Barbeque Nation is one of those "cook it yourself" places, where the center of the table is a small charcoal stove and the meats are delivered mostly-cooked on metal skewers. After marinating with a choice of marinades and allowing the food to cook the last 10% of the way, a delicious entree results. To make it even more acceptable to a western eater: it's all-you-can-eat, with skewers continually delivered until you tell them to stop. For the first time in a week, I was stuffed. It's very hard to turn down delicious seasoned and grilled meats when they keep arriving in front of you.

The ThoughtWorkers also had a number of interesting projects going on, many related to Ruby and a couple likely to use JRuby in the near future. Hakan had even worked on a code-generated implementation of the JRuby selector table's switch statements, which he promised to tidy up and send me. It could be very useful for us to optimize user-created classes in the same way we're starting to optimize core classes, and it was actually a technique we considered doing ourselves. More on that as it develops.

Tuesday, I packed up and checked out of the hotel. I was a little sad to be leaving Bangalore, but since I still had an entire day before my flight I walked up to M.G. Road to take care of some last minute souvenir shopping. My first stop was at Navaratna Jewelers for the modifications to my wife's new pearl necklace I mentioned earlier. While I waited for the work to be completed, I visited a few shops off the main boulevard and purchased the following items to bring home:
  • A small wooden Ganesha (about 4" tall), to bring success and prosperity to my office.
  • A small wooden Emblem of India, atop a 4" wooden column with a felt base. It is a perfect reminder of my Indian adventure (and probably the coolest national emblem I know). This is my favorite souvenir by far.
  • A small wooden puzzle box for my son.
  • Two larger versions of the puzzle-box with hand-painted images of Indian women on the tops.
I had also previously purchased the following items:
  • Two silk ties with different images of dancing elephants on them.
  • Two painted clay hippopotamuses, as gifts for whoever.
  • A comic/cartoon book of stories of "Heroes of the Mahabharata", for my boy to read.
For lunch, I was not feeling particularly adventurous, and also decided something familiar might be safest before 24 hours of plane flights, so I ate at Pizza Hut. Yeah, I know. It wasn't even that good.

Comfortably full from lunch and loaded down with all my new possessions, I returned to the hotel to catch a cab to the airport. Goodbye, Bangalore...or so I thought.

Bangalore Airport was to be a baffling ordeal. People were lined up for a solid block to get into the terminal, mostly encumbered with a half-dozen bags each. To confuse even more, there was an option whereby non-flying visitors could pay for admission to the terminal. Luckily, I figured out I didn't have to pay, and after muscling my way to the entrance, I moved on to the second challenge in this travel gauntlet: Thai Airways had no reservation for me.

My original tickets to India were incorrectly issued to "Charles Onutter", an unfortunate combination of my middle initial and last name. Normally, this wouldn't have been a big deal, but apparently international flights are extremely strict about the name for which tickets are issued. If it doesn't match your passport exactly, you're out of luck and can't check in. In a flurry of activity the day before I left, I managed to arrange new tickets. But because it was such short notice, I would have to buy two of my tickets at the originating airports: Sahara Air from Hyderabad to Bangalore and Thai Airways from Bangalore to Bangkok. Sahara air went fine...either because they found my reservation or because they had plenty of room on the flight. But Thai Airways had cancelled my reservation because they overbooked the flight.

Luckily, after talking to the ticket agents and American Express's emergency travel service, I was able to purchase an unused seat for the flight. I would fly first-class to Bangkok. I rushed through security, ran to the gate, and finally settled into my seat. Onward to the next stop in the tour: Bangkok, Thailand!

Friday, February 23, 2007

The Great Hyderabad Adventure

I have many pictures to share, but they will have to wait for an updated post. Allow your imagination to escort you for now.

So! I had been trapped in the "green zone" at the Novotel Hyderabad for two solid days, and I think I just finally had enough of it. The Novotel is surrounded by about five acres of land, and the edge of that property terminates with a heavy fence (or wall in places) with either barbed wire or razor wire keeping the rabble out...or perhaps keeping the westerners in? I had taken a few strolls on the grounds, and after walking a few hundred meters from one end to the other this morning, I realized I was tired of living in the bubble. It was time to leave.

A number of folks had expressed interest in escorting me into and around Hyderabad, but nothing materialized. Since this was my last chance to see the city, and potentially the last time I'd be in Hyderabad for many years, I had to take matters into my own hands. I asked the front desk for a map, a guidebook, and a few recommendations. Then the transportation desk set up a cab ride to my first destination, Charminar, the square, four-towered heart of the city. It was a perfect if clichéd place to start my day of exploration.

Unfortunately, Charminar is also right in the heart of the "old city", the other half of Hyderabad housing the less privileged portion of the population. Charminar itself was certainly astounding. Even though the minarets were closed, the view from the top main floor was quite impressive. In each of the four directions, thoroughfares stretched off into the distance, revealing a bustling mass of humanity. I could see the swarming rickshaws, the teeming bazaar, and the hoards of Hyderabadi citizens going about their lives. It was humbling really. But it was a bit more personal once I descended back into those masses to find my next destination.

India has truly awakened. Here more than anywhere I have visited the contrast between technology and tradition is grossly apparent. Construction projects involve teams of mean working by hand, like ants assembling a colony. But every ant has a cell phone with text messaging and a camera. In the streets, beggars clutch at you constantly, but often speak extremely capable English and understand the western world. Above, signs advertise BizTalk Server and Oracle Training. Below, people sleep in the streets and beg for pennies in roaring traffic. And in the streets of Hyderabad this paradoxical turmoil boils unabated.

So I climbed back down the stairs of Charminar, a bit concerned for my future. Walking out the secured gate, I was immediately mobbed by beggars, young and old. A few (usually the youngest) spoke surprisingly good English. They asked where I was from, what I needed, where I was going. Some (the older members of the hoard) only knew what they needed to elicit a response from western hearts and minds..."food"..."baby"..."hungry"..."please". Why exactly had I decided to launch into this city alone? Ahh, for adventure, I remember. And what happens at this point in an adventure? When the odds and numbers are stacked against you? A gallant escape, with nary a rupee spared. How noble of me.

No, I did not make a contribution to the Hyderabadi poor. I certainly could have. Is it heartless of me? I don't think so; to have made one contribution would have certainly brought a torrent upon me, and it was already a worrisome situation. Instead, I made for a nest of rickshaws near the monument. One particularly bold youth, Abdul, stepped out of the crowd with a map of monuments, a plan for visiting them, and a welcoming smile. He was a salesman with exactly the product I needed, and for the next six hours he would be my guide. Off we went.

One of the previous would-be escorts had suggested Golkonda Fort as a place I should not miss. So naturally, with a friendly and aware guide at my side, that was the next place to visit.

Golkonda is the ruined former home of the Qutub Shahis, before they moved their home to what is now Hyderabad. It is an extensive maze of towers, walls, tunnels, temples, mosques, and overlooks atop a the highest hill in the area. After climbing several hundred feet to the summit, the sprawl of the city extends in all directions. No other view in Hyderabad gives such a complete picture of its size and extent. The fort itself is also impressive, with four-story defensive walls, a remarkable acoustic communication system, and numerous gardens tucked away behind tunnels and through towering arches. The climb to the top required a few breaks, during which Abdul told me what he knew of the fort's history in broken English and snapped photos of me at the major landmarks.

Eventually, we descended, and headed for the next stop on the tour: the Qutub Shahi Tombs.

There were seven Qutub Shahi kings, and they are all interned here in monumental tombs. Each tomb hosts an enormous dome (complete with perfect acoustics for singing, chanting, or tourists clapping and hooting), multiple entrances and side-tunnels, and inside the center, a symbolic (or perhaps more-than-symbolic?) monument to the hosted monarch. Most of the tombs contain a single such monument, but one had three: mother, father, and child. There are tombs here for the seven kings, many of their wives, and other relations. The writing on the monuments is in Arabic. That on the tour signs, in Telugu. Both Hindi and Muslim visit and pay their respects. And the city surrounds. I would say that the Qutub Shahi Tombs are at least as important a stop as the Golkonda Fort. If you are to visit the height of the kings' success, you should at least say an appropriate goodbye.

The rest of my adventure is somewhat less compelling, but perhaps still interesting. Hyderabad as we know it in the western world is really two cities to the Indians: Hyderabad and Secunderabad. In a peculiar quirk of fate, this pair is known to most Indians as "The Twin Cities", just like my home towns of Minneapolis and St Paul are known to Minnesotans (and many Americans) as "The Twin Cities". The very center of Hyderabad, bridging these two cities, is a large lake called Hussein Sagal. Arriving here, I have come full-circle to the heart of the "Twin Cities" on the other side of the world. Unfortunately, the interesting part of that story ends here. Hussein Sagal now appears to be little more than a tourist trap, firmly ensconced in the "new" part of the city. It is surrounded by miraculous science museums and modern family amusement parks. Put simply, I had no interest in anything more than driving past. Yes, it's a large lake in the middle of the city. Yes, there's a 60-foot-tall Buddha standing in the center. The noise of the traffic surrounding and the lights of the shopping malls and Pepsi signs tends to dampen any beauty or majesty that once was there. We moved on.

One item I had expressed interest in when talking to the front desk was "shopping". Unfortunately, we had different definitions of shopping. To me, shopping was visiting a "bazaar of the people", where I could browse sarees for my wife, hand-made toys for my son, and myriad other handicraft and localities. To the hotel, shopping meant "Macy's".

360s, $1 The final stop on my 8-hour Hyderabad tour was, sadly, the LifeStyle department store. It wasn't a bad store, really, since it did host a few local items and the prices were a little better than those at home. But it was a truly western-style store, with little interest to me as anything other than a landing zone. I wandered up to its second story, where I found discounted XBoxVCDs, and a coffee shop so grossly plastered with Windows Vista branding that they even had a "Windows Logo" menu prouding selling "Windows Vista WOWffee". Naturally, I ordered one due to the sheer absurdity of getting a free "Vista Wristlet", a white rubber bracelet emblazoned with the words "Windows Vista. The "Wow" starts here." To make it even more stomach-turning, it was a latte with orange flavoring. Delicious.

Of course I couldn't let the day end with a "WOWffee" and high-quality merchandise at low, low prices, so I called a fellow Sunny from the hotel to join me for a very satisfactory dinner. And then, after consuming excessive amounts of vegetable biriyani, chicken tikka masala, and garlic naan, I returned to the "green zone".

So what have I learned from my excursion?

  1. Exploring the poor districts of an unknown city alone can be frightening, but it certainly gives one perspective on the meaningless nonsense we labor over in the western world.
  2. Don't wait for someone to show you the world; just go see it yourself.
  3. The world is disappearing...so you better see it soon.
I hope I can return to Hyderabad some day to see more of its hidden treasures. For now, I move on to the next JRuby World Tour Stop: BANGALORE.

Wednesday, February 21, 2007

Tech Days Talk a Success

I just completed my talk at Tech Days Hyderabad, and I think it was resounding success. If I heard right, the total head count for my "JRuby Essentials" talk was over 1200 people, by far the largest crowd I've presented for. There was a hoard of questioners immediately after the talk, who followed me into the hall to keep asking. I gave out my entire in-pocket batch of business cards, and even received a round of applause after the JRuby on Rails demo. All this even after my talk was delayed and cut to 40 minutes because the earlier talks ran too long. It was a sprint, but I think it went very well.

I will be posting the slides, but they're basically the same content many of you have probably seen the past couple months. For those who haven't had the pleasure, we'll start posting slides more regularly, and I'll try to blog a few example walkthroughs for those of you who want to duplicate them for your own talks. Feel free to steal it all and spread the word.

Tuesday, February 20, 2007

JRuby World Tour: Hyderabad

Success! It is now 3:00AM in Hyderabad India, and I have checked into the Novotel in HiTec City. The flight was uneventful; I got my demos basically working and then slept the majority of the time. The immigration and customs at the airport were perhaps the least threatening of any I've seen. Immigrations basically just looked for my visa, took my arrival card, and stamped my passport. Customs was little more than a big white X-ray machine with "CUSTOMS" printed on a white piece of paper taped to the front.

The smooth arrival was just what the doctor ordered. The reason I'm on this round-the-globe trip is because my original tickets to India were issued to the wrong name: Charles O'Nutter instead of Charles (O) Nutter. I never noticed the slip-up on the itinerary (nor would I ever have recognized it as a slip-up, since the output was pretty mainframe-ish), and only upon arriving at the airport in Minneapolis was I told I could not check in. Twenty-four hours and a lot of scrambling later, I had new tickets issued on the only flights available, hence my return trip heading east via Bangkok and Tokyo. But aside from that initial snafu, the trip has been pretty routine. Saturday will be interesting...my ticket to Bangalore has to be purchased in-person, so there's great potential for more headaches. But I can take it in stride, and I'm sure things will work out well in the end.

Hyderabad is about what I expected, and I'm looking forward to getting into the city one of these three days before I leave for Bangalore. It feels very similar to Beijing, with old meeting new and construction everywhere. The city looks very appealing; street-level shops line almost every sidewalk, there's green plant life everywhere, and everything has sort of a dusty, dingy, comfortable feel. It's not dirty, don't get me wrong...just dusty, like any city kicking earth into the air with a thousand construction projects might be. The auto-rickshaws (three-wheeled rickshaw-looking things with small engines) are pervasive; I can imagine that during the day they swarm and buzz like bees. They drive on the British side of the road, which isn't much of a surprise, really.

It's really unfortunate when traveling to more exotic places like this that I have to check into a tidy, pristine western-style hotel. I'd rather stay in the midst of the city, where I can walk out the front door into daily Hyderabadian life. I doubt I'll be at the hotel for all three days of the conference...there's exploring to be done.

If you're located in Hyderabad or Bangalore and might be able to show me around a day this week (Thursday or Friday for Hyderabad) or next Sunday or Tuesday (Bangalore) I'd appreciate it. I'm not put off by crowds of people, even if many don't speak my language, but knowing the hot spots for shopping and eating makes exploring a bit more productive.

I give my presentation in just over 12 hours, so I'm going to try to settle in with a nice Kingfisher lager beer and relax. The conference schedule has things starting up in about 6 hours, so I should be fine for sleep and fairly well-delagged by then.

On the plane, I managed to duplicate the rails-integration WARfile-based deployment of a simple webapp, but I was unable to get an embedded Derby DB to work with it. I'm sure it's a matter of permissions, connection pooling, and such. I may or may not have time to get that working by tomorrow, but if I demo the basic app working with WEBrick and then WAR it up and show the non-DB stuff working in GlassFish, I think the point will have been made. I must also keep reminding myself that my talk is only 50 minutes now. I can fill 50 minutes without batting an eye. So we'll see if there's even time to get to GlassFish, since it eats up a good five minutes building and deploying the app from scratch.

JRuby World Tour: Amsterdam

I'm now relaxing at Schiphol Airport, where I've just plunked down my 10 euros for internet access. After a light breakfast, my current task is now to ensure demos are ready and working for TechDays. I discovered a bit ago that the Rails Integration project uses maven to build, and so I need internet access for that first install command (to pull down required dependencies). I had worried a bit about finding internet access, but this connection appears to be pretty good. I've managed to build the Rails Integration module, and hopefully I'll be able to get Rails-in-a-WARfile working in the next few hours.

If I discover anything interesting in the process, I'll post it. From what I've observed, the rails-integration guys and Ashish have had lots of success lately.

If you happen to be at Schiphol before I depart at 11:55, I'm in Lounge 2 near the brasserie. I'm the one with the MacBook Pro, fighting jetlag and overlooking the concourse.

The next stop will be Hyderabad. My 11:55 flight departs from gate F8.

Update: I managed to get Rails up and running nicely in a WAR file. Huzzah! I'll play with it a bit on the plane and get our usual Rails demo to feed directly into "now we'll make it a WAR file". Thanks much to the rails-integration guys for putting together a really slick piece of work. Gotta love this whole open-source thing.

Side note: jet lag is a weird feeling. Right now it's 9:49 in Amsterdam and around 14:19 in Hyderabad, so I have to pretend it's mid-afternoon. My flight will board in about two hours, and toward the end of the flight I'll have to pretend it's evening and start getting a little sleep. It's quite unfortunate that I'm arriving in Hyderabad at 1:20AM on the day I'm presenting, but that's how it goes!

Sunday, February 18, 2007

The JRuby WORLD TOUR 2007

Yes, you read that right! I'm announcing my intent to circumnavigate the globe in only NINE DAYS spreading JRuby and joy at every stop. The Earth shall be wrapped in JRuby goodness!

To celebrate this monumental occasion, I'm inviting all developers with an interest in Ruby or Java to join the JRuby mailing lists and volunteer your services. Eternal gratitude and temporary fame could be yours, for the small price of bug reports, bug fixes, or high-performance rewrites of core JRuby libraries (it's so easy!). Operators are standing by to receive your emails and direct you to the promised land!

Now, on to the tour!

First Stop: Amsterdam, Netherlands

The first leg of my journey takes me from my home in Minneapolis, Minnesota to beautiful Amsterdam. There I will enjoy an delicious airport breakfast followed by a five-hour tour of the terminal. I will be available for autograph signing from 7:00 to 11:30 by appointment only. The first annual JRuby New-Age Concert of Magic will follow from 11:30 to 11:35. Tickets are first-come, first-served; cash only, please! I will depart from Amsterdam at 11:55 via a chartered jet I'm generously sharing with three-hundred other passengers and a small KLM Dutch Airways flight crew, en route to exotic Hyderabad, India!

Second Stop: Hyderabad, India

The next part of the JRuby "World Domination Tour 2007" takes me to Sun's Tech Days event in Hyderabad. In addition to my JRuby session, Tech Days will host such scintillating topics as "iPod Giveaway" and "Java Jacket Giveaway". But on Wednesday the 21st at 3:35PM you too can learn why JRuby is the programming alchemist's "Developer's Stone", transmuting static lead into dynamic gold. The topics covered will be exactly like those in recent JRuby talks, except cooler, faster, and after 26 hours of non-stop travel and five hours of sleep. Prepare for a punchy, laugh-riotous affair! Will I be able to maintain 90WPM during my interactive demonstrations? Will I remember that "alias" takes two arguments *without* a comma and with the original method first? Join me for what's sure to be 50 minutes you'll remember the rest of your life!

Third Stop: Bangalore, India

From Hyderabad, I take a short one-hour flight to Bangalore, home to Sun Microsystems India and the third leg of the JRuby Globe-trotting Festival of Light! On Monday, February 23rd, I will present JRuby to my tropical counterparts on the opposite side of the earth, featuring the exact same topics from Tech Days...in RANDOM ORDER. You never know what I'm going to do next.

I actually have all that Sunday free and Tuesday up until about 8:00 free to do some exploring. Event suggestions are welcome, and I challenge any of you to find food too spicy for me to eat! (impossible, I say!)

Fourth Stop: Bangkok, Thailand

The next step takes me from Bangalore to beautiful Thailand, jewel of Southeast Asia and home to one of my favorite cuisines. I will be available from 4:00AM to 5:30AM for a special, once-of-a-lifetime event I'm calling "JRuby Dawn at Bangkok Airport". And the great question on everyone's lips will be foremost on my mind:

Will the airport's Thai restaurants open before I board my next flight at 6:00? Stay Tuned!

Fifth Stop: Tokyo, Japan

Continuing the Asian leg of the tour, I'll spend 80 fun-filled minutes exploring the international terminal in Narita, only an hour's train ride from the Emperor's Palace! Naturally I'll be available for handshakes and baby-kissing, and hopefully the always-humorous photograph of "buying beer from a vending machine". This trip will serve as a preview for the main Tokyo event: Ruby Kaigi 2007 in June, where I'll finally present JRuby to the Land of the Rising Sun. Come 3:10PM it's time for "so long Japan", but I'll be back soon!

Sixth Stop: Minneapolis, Minnesota

And just 9 days after I departed, I'll be home in Minneapolis again, ready for my next thrilling adventure: The Greater Wisconsin Software Symposium (a No Fluff Just Stuff event) in Milwaukee from March 2-4. Join me for my two fabulous sessions "Bringing Ruby and Rails to the JVM" and "Become Super-Powerful with JRuby", putting the greatest dynamic language ever in the palm of your JVM.

Wednesday, February 14, 2007

Jython 2.2 Beta 1 Released!

The Phoenix Is Rising!

After being considered dead for many years, Jython is back in business with the beta 1 release of Jython 2.2. It's been teetering on the edge of 2.2 compatibility for a long time, but over the past several months the core team and several contributors have rounded off the edges, to the point that a beta release of the long-awaited 2.2 version is now available.

For all you Pythonistas, this should mean two things:

- You have a project for the day. Go get Jython 2.2, try it out with your Python 2.2-compatible apps and libraries, and report any issues you find.
- Start contributing your time, either helping with the Java coding, helping to debug Python apps and libraries, or help on efforts to write C-based libraries in Python.

I will also remind you that a large percentage of JRuby's success is due entirely to its community. Can you really get up in the morning and look at yourself in the mirror without knowing you've helped Jython get back up to speed? Can you?

Tuesday, February 13, 2007

Rails Support Status Update

Things are moving along well...so well I've found time to reimplement String with byte[], work on closures in the compiler, and, well those are posts for another day. Today I update you on the progress of supporting Rails in JRuby.

Rails is quite an interesting beast. I've learned more about Ruby looking through Rails code than from any other source...out of sheer necessity. They say the best way to learn a language is through immersion, right? Is debugging 50-deep stack traces on a questionable interpreter, digging for a reducible test case immersive enough for you? Yeah, I thought so.

We actually hit Rails support hard right at the beginning of this month, or the end of January. The early results were pretty solid, so our efforts have been distracted onto other large JRuby issues not necessarily Rails-related (but all still critical for an eventual 1.0). We also made the bold move of jumping to Rails 1.2.x for all our testing, to show we can keep up with the Rails development process. And to show that we've made great progress, I give you the following results.

ActiveSupport

ActiveSupport is the base module for Rails. It monkey-patches a number of core classes, provides a multibyte String wrapper for UTF-8 encoded text, and handles most of the details of running and configuring an application. It "supports" the other libraries, and is the first crucial leg needed to run Rails. And so we must "support" it well.

Here's the current results of a full test run:

498 tests, 1809 assertions, 16 failures, 6 errors

That's already in the 95% range, so we're in darn good shape. But it turns out a number of these errors are caused by a glitch in our parser related to KCODE. So if we work around that known issue, the results improve to:

498 tests, 1845 assertions, 12 failures, 1 errors

So more like 97% passing once we fix the KCODE parser problem. The remaining issues are almost all related to time-formatting bugs, with a couple multibyte and exception-handling issues tossed in. I haven't attacked the formatting bugs because Printf code is bloody painful, the multibyte issues are waiting on the KCODE parser fix, and the others...well, they're boring.

ActionPack

ActionPack is the brains of a Rails app, housing the mechanisms for controllers, views, and any code to support them. So it's leg two of the crucial three-legged support necessary to run a Rails application.

I hit ActionPack hard in the past, and a bit this month. Ola took off with it and completed most of the remaining failures. Running with the same KCODE workaround, we have the following results today:

1157 tests, 4811 assertions, 7 failures, 14 errors

That's above 98% passing. The remaining failures include a number of dupes (a single failure that breaks a number of tests), some additional string-formatting failures, and a couple that run ok outside of Rake. So it's damn close to perfect.

ActiveRecord

You should all know ActiveRecord by now, right? It's Rails' DB layer, based on the ActiveRecord pattern. It is the third core leg of the Rails platform, though you can certainly have apps that don't use AR for database support.

ActiveRecord is an extensive piece of code and it's the only part of Rails that usually requires a native library to run properly (though there is a pure Ruby impl of its MySQL support that nobody uses). In order to support AR, a number of the JRuby community members have cooperated over the past 9 months to build ActiveRecord-JDBC, a gem-installable module that provides ActiveRecord DB support via JDBC. It's a great bit of hackery, and runs surprisingly well considering our less-than-beautiful Java integration performance (under repair).

To limit the scope of this month's Rails work, we're targetting MySQL, since it's the de-facto standard for Rails apps in most quarters. But most of the work we're doing will apply equally well to the other databases, since JDBC is generally very consistent. Tom has been spending lots of time on Derby, for example, to the point that our ActiveRecord-on-Derby failures are almost entirely limited to SQL features it doesn't support yet.

So then ActiveRecord test results, minus the KCODE workaround (since Tom ran these for me):

1012 tests, 3417 assertions, 41 failures, 35 errors

Here our results dip to around 92% passing, but it's really the extended features of AR that have failures here. We've come a long way on this; results on the months-outdated JRuby wiki show Rails 1.1.6's ActiveRecord only passing about 60% of that release's tests, so there's been a ton of improvement since November. And we generally understand how to fix the remaining failures, so it's only a matter of (short) time.

ActionMailer

Can you guess what ActionMailer does? ActionMailer provides support for composing, formatting, and sending email from a Rails app. And that's about it. It's not a huge library, but it's essential for many apps.

64 tests, 142 assertions, 9 failures, 6 errors

That's about 75% passing, with a grand total of six test scripts. We haven't focused on this much, other than Tom's initial KCODE work a few months back. The current failures are almost all mail-formatting or SMTP-wrangling issues. I don't expect them to be hard to repair.

ActionWebservice

Because ActionWebservice's tests require some database setup, we haven't tackled them yet. But I would lay even money that they'll be comparable to ActiveRecord at their worst. For now, they all just fail because MySQL isn't set up correctly for them.

96 tests, 0 assertions, 0 failures, 96 errors

Any community member that wants to dive into ActionWebservice or ActionMailer would fast become a JRuby Hero.

Railties

Railties is the final piece of the Rails puzzle, and it...well..."ties Rails" together. I show the results here mostly for completeness; many of the libraries in Railties we'll never support (fcgi, for example) and most JRuby-on-Rails deployments will use alternative mechanisms for hitting the web.

5 tests, 19 assertions, 2 failures, 0 errors

Official Rails Support?

Because things are looking pretty solid, we've been looking for an answer to this question: What does Rails Support in JRuby mean? Do we have to pass all test cases 100% to "officially" support Rails? That might never happen, since there's POSIX and external library stuff we won't ever handle (nor will we need to for JRuby on Rails apps). So then is it a certain percentage? 95%? 98%?

I think the truth is that we could really announce support for Rails now. Almost all the visible, outstanding issues with actually *running* Rails apps have been resolved, and most apps and scripts work fine. There's ongoing work to improve ActiveRecord-JDBC's support for other databases, but that's an endless quest. And of course there's more work needed to support Grizzly, Mongrel, and WAR-based deployment of JRuby on Rails, but those are peripheral to the official announcement. Even when we do make an official announcement, it will be for a pre-1.0 version of JRuby, since we know there's another few months left on 1.0 fixes and features.

So what do you think, dear reader? At what point would you feel safe saying "Let's have our non-JRuby hackers try using JRuby on Rails"? You probably would *be* safe right now, since even if you found issues we've got a busy community ready to help solve them. And we'll probably tiptoe closer to "perfect" Rails support in JRuby over the next couple months, chasing the long tail of Ruby compatibility. But how do these numbers and this update make you feel about JRuby on Rails today?

And as always, we love to have additional contributors, so we'll bend over backwards to make it easy for you to help. Join the lists, join #jruby on freenode IRC, or toss us email privately. JRuby is an amazing community-driven success story, and the only thing missing is you.

California Schemin'

Last week Tim Bray and I were at Menlo Park to meet with the Open Source Software Society Shimane, a delegation of developers, managers, and company heads from the Shimane prefecture of Japan. They were visiting Sun to talk with us about opportunities for cooperation, Sun hardware and software, and most importantly: Ruby. For you see Shimane is the home of Yukihiro "Matz" Matsumoto, creator of Ruby, and he accompanied the group to California.

The evening before the event, we went to Fuki Sushi in Palo Alto, a short two blocks from my hotel. I don't believe I've ever eaten such quantity or variety of Japanese cuisine, and I think our guests felt the same way. They marveled at the size of most dishes, especially the ice-cream-scoop-sized lump of wasabi and the two-foot-long sushi tray. They also photographed almost everything...I think I posed for a couple dozen snaps.

During the following day, Thursday, they sat through numerous presentations on Sun hardware and software. Tim and I also discussed Sun's position on Ruby and JRuby for an hour before and about forty minutes after lunch. Tim hit the high-level points about where Ruby will likely fit into the Java ecosystem in the future, and I supplied details and demos of JRuby. I also threw in a demo of JRuby's compiler beating Ruby 1.8 in the standard fib algorithm, which elicited a smile and laugh from Matz himself (whew! I was worried how he'd react!).

Most interesting to me, however, was my discussion with Matz that night.

I was invited to join the delegation for a crab dinner in San Francisco. We went to Crustacean, a moderately upscale joint near California and 101. And after the attendant tied my plastic bib on, we were ready to go.

Since Matz and I ended up sitting together, and since very few others at the table spoke English, we managed to get in some time discussing a couple Ruby 2.0 design issues. Here's a quick summary:

  • Matz seems to have come around to my visibility proposal for "private" in Ruby 2.0, which is largely the same as how Java handles private visibility. I believe this model is a good simplification over the original proposal. See ruby-core:9996 and related for the original discussion. The basic facts of private then would be:
    • You must dispatch to private methods using a functional call, as in foo() versus xyz.foo(). I didn't like this at first, but I've come around to using call syntax to force certain aspects of visibility.
    • Dispatches to private methods will only look in the same class for the method definition.
    • Methods that are public in superclasses can't be made private in subclasses.
    • Methods that are private in superclasses are not visible to subclasses, and so new methods of the same name and any visibility can exist in subclasses.
  • Protected methods in Ruby 2.0 could potentially act like private methods now, though Matz is worried it would be too much of a change. I think it's appropriate; current private method behavior is very similar to Java's model for protected methods, where the methods can't be seen from outside the hierarchy, but can be called and overridden within the hierarchy as normal. I voiced my opinion, so we'll see where Matz goes from here.
  • Matz is still comfortable with removing set_trace_func if a better mechanism for profiling and debugging can replace it. I had a few suggestions for alternate mechanisms, but I also promised to look into Java's model, since it seems to work quite well. I also suggested there may be something to learn from DTrace.
  • Matz has come around to the idea that encoded character sequences are a different type than unencoded byte arrays, though he still wants them to have the same outward interface.
This last item warrants a bit more discussion.

The topic of encoded character strings came up a few times during Matz's visit, usually with him asking how we're doing things in JRuby. I explained that we mostly just follow Ruby 1.8, with our String now being backed by a byte[], but that we're also providing out-of-the-box native support for the new Rails ActiveSupport::MultiByte Chars class, a wrapper around string that enforces character boundaries and encodings.

At dinner, we continued the discussion. I made my case for a separate type with the following points:
  • A separate type would not require String's interface to change, and it could remain a byte array
  • By having separate types, we can use polymorphic behavior to avoid checking and re-checking encodings for every operation
The first item was mostly a non-issue...Matz is fairly intent on changing the String interface in 2.0, and much of that work is already complete. But he had an interesting response to the second item: he's already planning to have separate types internally for encoded character strings. This was very good news to me, since it meant that JRuby could easily support M17N in the future by simply providing different String types that handle the other encodings, where our UTF-16 String implementation could simply be backed up by java.lang.String/StringBuffer/Builder.

So the result of the String discussion can be summarized in a few points:
  • String's interface will change from 1.8 to work with characters rather than bytes, both in the encoded and unencoded forms of String. The plan for String methods' behaviors does not change from current Ruby 1.9.
  • String will have subtypes that represent encoded character data, though in most cases you won't need to know about those types. If you do need to go after a UTF8String (my name), you can, but there will also be some sort of factory model for generating encoded strings and Ruby 2's encoding pragma will handle literals.
All told, I think it was a very productive trip, and it was great to help Matz work through a few Ruby 2.0 design questions.