Projects
Home     Blog     Install     New Ticket     View Tickets     Browse Source

Why MacRuby?

MacRuby is an attempt to work around many problems that the Ruby 1.8 + RubyCocoa combination currently experiences.

Problems

As a purely interpreted solution, it doesn't perform well enough to write critical logic in RubyCocoa applications that require high runtime performance.

MacRuby is based on Ruby 1.9, powered by the YARV bytecode interpreter, which greatly reduces the execution time of Ruby programs.

The class and object model has to be maintained on both sides, creating intermediate proxy objects when necessary, which is both painful and error prone.

Objects and exceptions must be converted from one type to another when they cross the bridge, which has a significant performance impact.

Instances much be cached, to avoid multiple proxies for the same instance, and appropriately invalidated. Some objects cannot be cached because there is no reliable way to invalidate them.

In MacRuby, all Ruby classes and objects are actually Objective-C classes and objects. There is no need to create costly proxies, convert objects and cache instances. A Ruby object can be toll-free casted at the C level as an Objective-C object, and the Ruby VM can also handle incoming Objective-C objects without conversion.

Also, the primitive Ruby classes, such as String, Array and Hash in MacRuby have been re-implemented on top of their Cocoa equivalents, respectively NSString, NSArray and NSDictionary. As an example, all strings in MacRuby are Cocoa strings, and can be passed to underlying C or Objective-C APIs that expect Cocoa strings without requiring a conversion. And it is possible to call any method of the String interface on any Cocoa string too.

The Objective-C calling syntax doesn't translate well to idiomatic Ruby when used from RubyCocoa. As an example, the setObject:forKey: selector is transformed to setObject_forKey_, replacing colons with underscores.

MacRuby enhanced the existing Ruby syntax to allow keyed arguments, as in Objective-C. As an example, you call dict.setObject(o, forKey:k). The new syntax can be used to send messages, but also to define new Objective-C methods.

Because the Ruby 1.8 runtime is not thread safe, it is impossible to callback to it in a different POSIX thread. RubyCocoa was modified to route calls from other threads to the main one, but it doesn't scale very well and it can sometimes cause deadlocks.

The Ruby 1.8 threading model uses green (emulated) threads. Calling Cocoa from a Ruby thread might cause unexpected problems, because in many places in Cocoa uses per-native-thread data. Both Ruby and RubyCocoa in Leopard were modified to appropriately save and restore autorelease pools and exception handlers, which are the most important per-thread data in Cocoa. While this works in most cases, this is clearly a non-optimal.

The threading model in Ruby 1.9 has been significantly improved to allow multiple threads to callback to the runtime. Also, Ruby threads in 1.9 are now native POSIX threads.

The Ruby garbage collector performs slow collections while stopping the program flow, and doesn't integrate very well with the Objective-C garbage collector.

MacRuby doesn't use the traditional Ruby garbage collector, but instead uses the Objective-C garbage collector, which is new in Mac OS X 10.5 (Leopard). The new Objective-C garbage collector engine, due to its generational nature, performs fast collections. It also doesn't stop the world while collecting memory, because collections are done in a separate thread.

Want to know more? Please follow with HowDoesMacRubyWork and MacRubyTutorial.