Blog Overview
MacRuby trunk got a new build system, entirely written with Rake. We managed to replace the previous autotools-based build system with a 570 lines of code Rakefile (which can still be refactored). We didn’t really need autotools since MacRuby aims to be installed on only one platform: Mac OS X. Maintaining the autotools files were really difficult, and we are very glad to now have a pure-Ruby build script.
Building and installing MacRuby is now very simple:
$ rake $ sudo rake install
This will build and install MacRuby in /Library/Frameworks/MacRuby.framework, executable symbolic links in /usr/local/bin (with a “mac” prefix, for example “macruby”), Xcode templates and sample code.
To see the list of all tasks;
$ rake -T (in /Volumes/Data/src/MacRuby) rake all # Build MacRuby and extensions rake clean # Clean local and extension build files rake clean:ext # Clean extension build files rake clean:local # Clean local build files rake config_h # Create config.h rake default # Same as all rake extensions # Build extensions rake framework:info_plist # Create the plist file for the framework rake framework:install # Install the framework rake install # Same as framework:install rake macruby # Same as macruby:build rake macruby:build # Build MacRuby rake macruby:dylib # Build dynamic libraries for MacRuby rake macruby:static # Build static libraries for MacRuby rake miniruby # Create miniruby rake objects # Build known objects rake rbconfig # Create config file rake sample_test # Run the sample tests rake test # Same as sample_test
Also, MacRuby trunk has a faster Objective-C dispatcher. Around 4 times faster that MacRuby 0.2 (and way faster than RubyCocoa). This was possible by fixing bugs in the dispatcher and also cache some of the runtime information.
Let’s consider the following Objective-C class.
$ cat dummy.m
#import <Foundation/Foundation.h>
@interface Dummy : NSObject
@end
@implementation Dummy
- (id)doSomething
{
return @"";
}
- (id)doSomethingWith:(id)value
{
return value;
}
@end
void Init_dummy (void) {}
We can build it as a Ruby extension.
$ gcc dummy.m -o dummy.bundle -framework Foundation -dynamiclib -fobjc-gc"
Then, test calling the methods. First, the doSomething method, which is a very simple case.
$ ruby start.rb ruby -v -r osx/foundation -I. -r dummy -e "include OSX; o = Dummy.new; 1_000_000.times { o.doSomething }"
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
5.295735
5.290816
5.28286
$ ../miniruby02 -v -I. -r dummy -e "o = Dummy.new; 1_000_000.times { o.doSomething }"
MacRuby version 0.2 (ruby 1.9.0 2008-06-03) [universal-darwin9.0]
2.977553
2.98855
2.984585
$ ../miniruby -v -I. -r dummy -e "o = Dummy.new; 1_000_000.times { o.doSomething }"
MacRuby version 0.3 (ruby 1.9.0 2008-06-03) [universal-darwin9.0]
0.639648
0.65196
0.644522
Then, the doSomethingWith: method, a bit more complicated because one argument is passed, so both RubyCocoa and MacRuby are using libffi to call it.
$ ruby -v -r osx/foundation -I. -r dummy -e "include OSX; o = Dummy.new; o2 = 'foo'; 1_000_000.times { o.doSomethingWith(o2) }"
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
13.981403
13.943761
13.936082
$ ../miniruby02 -v -I. -r dummy -e "o = Dummy.new; o2 = 'foo'; 1_000_000.times { o.doSomethingWith(o2) }"
MacRuby version 0.2 (ruby 1.9.0 2008-06-03) [universal-darwin9.0]
7.267144
7.210777
7.267988
$ ../miniruby -v -I. -r dummy -e "o = Dummy.new; o2 = 'foo'; 1_000_000.times { o.doSomethingWith(o2) }"
MacRuby version 0.3 (ruby 1.9.0 2008-06-03) [universal-darwin9.0]
1.239323
1.259157
1.246987
These are very premature results, we expect to continue reducing the time spent in the dispatcher, in the near future, and hopefully to make it twice faster.
On a side note, Konrad M. Lawson was kind enough to generate a very nice screencast of MacRuby demonstrating the Xcode/IB integration. Thanks Konrad!
After 3 months of development, here comes the second release of MacRuby, 0.2! Check it out while it’s hot!
This is an important release which addresses many bugs but also re-implements parts of the runtime using the CoreFoundation framework.
In MacRuby 0.2, all strings, arrays and hashes are now native Cocoa types, represented by NSString, NSArray and NSDictionary objects, respectively.
The entire String, Array and Hash interface was rewritten on top of the Cocoa equivalents using the powerful CoreFoundation framework.
The previous implementation, inherited from MRI, is not used anymore. The rationale behind this change is simple:
It is no longer necessary to convert Ruby primitive types to Cocoa or vice-versa. For example, a String created in MacRuby can be passed as is, without conversion, to an underlying C or Objective-C API that expects an NSString. Similarly, any method of the Ruby String class can be performed on an NSString that comes from Objective-C.
Interestingly, the CoreFoundation implementation that MacRuby now uses has proven itself to be stable and performs quite well, even this early in the implementation process.
We did not work on any performance improvements for MacRuby 0.2 (we will address performance in the next upcoming release), but we noticed some dramatic performance gains in some areas nonetheless.
Inserting elements in an array is faster in MacRuby than the original 1.9 implementation, for example, mostly because CFArray switches on the fly its data structure to an implementation that performs well according to the current number of elements.
a=[]; 100_000.times { |i| a.insert(0, i) }
MacRuby version 0.2 (ruby 1.9.0 2008-06-03) [universal-darwin9.0]
0.326057
0.318714
0.314731
ruby 1.9.0 (2008-06-03 revision 16762) [i686-darwin9.0.0]
4.308484
4.382623
4.36368
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
4.608796
4.595334
4.581045
Regarding hashes, searching for a specific value (which isn’t something that is typically done) is shown to be faster. k
h = Hash[*(1..10000).to_a]; 10000.times { |i| h.has_value?(i) }
MacRuby version 0.2 (ruby 1.9.0 2008-06-03) [universal-darwin9.0]
0.965304
0.955293
0.950316
ruby 1.9.0 (2008-06-03 revision 16762) [i686-darwin9.0.0]
3.790461
3.804271
3.815217
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
4.225632
4.225457
4.239244
And to finish with strings, it turns out that manipulations on multi-byte strings are faster in MacRuby than 1.9.
$ cat t3.rb
# -*- coding: utf-8 -*-
s = "わたしはロランです。" * 2000
s.length.times { |i| s[i] }
$ ruby b.rb t3.rb
MacRuby version 0.2 (ruby 1.9.0 2008-06-03) [universal-darwin9.0]
0.180019
0.180165
0.177425
ruby 1.9.0 (2008-06-03 revision 16762) [i686-darwin9.0.0]
1.624943
1.633502
1.62767
Speaking of strings, since every of them is now a CFString, they get for free features that weren’t present in the original 1.9 implementation, such as ICU transformations for example:
$ cat t3.rb
puts "watashiha".transform('Latin-Hiragana') +
"lauren".transform('Latin-Katakana') +
"desu.".transform('Latin-Hiragana')
$ macruby -v t3.rb
MacRuby version 0.2 (ruby 1.9.0 2008-05-17) [universal-darwin9.0]
わたしはラウレンです。
MacRuby is still slower in many cases, including very important ones such as objects allocation and methods dispatch. There are also too many areas in String, Array and Hash where we perform much less well than we should.
We plan to address this in the next release (0.3) as well as many other things, so stay tuned!
Very recently some new projects using RubyCocoa were released to the public.
TimeToTicket, a tool to report your working hours in the RedMine project management system.
CocoaNav, an application to elegantly browse frameworks and classes. Very cool animations.
osx_trash, a command-line tool to easily manipulate the Mac OS X Finder’s trash.
And, it’s hard to not mention GitNub, a desktop frontend to the git source control management system. This isn’t really a new project, but it’s starting to be popular in the development community.
This really demonstrates that RubyCocoa is being adopted by more people, and more importantly, Ruby as a language to write Mac OS X applications. And the future is not that far now!
« newer | Page 4 of 4 | older »