RubyMotionはRubyでiOSとOS X向けのアプリケーションを開発するためのツールチェーンを提供する。LLVMベースのコンパイラを使ってネイティブコードにコンパイルされるのだ。3.0のリリースでは、Androidもサポートする。Androidでの開発プロセスはiOSと似ている。ビルドとアプリの実行、マニュフェストの生成とリソースのハンドルにはrakeを使う。
Androidバージョン向けに、HipByteは新しいRubyランタイムをスクラッチから開発した。性能とJavaとの互換性を改善するため、Rubyのコアクラス(Fixnum, String, Arrayなど)がJavaの対応するクラスに基づいて開発された。
この統一ランタイムを使った方法はJavaのAPIとしっかりと統合でき、性能も優れています。オブジェクトをブリッジする必要がないからです。ランタイムはJava Native Interface (JNI)を使ってJavaと統合されます。AndroidのAPIのすべてがRubyから使えます。
メモリの管理はDalvikの世代並列ガベージコレクタに委譲されます。ランタイムは必要なときにグローバルな参照を作成し、削除します。ローカル参照の削除はコンパイル時に決まります。
ガベージコレクタはとても効率的です。スレッド毎のアロケーションプールを使うことで高速なアロケーションを実現し、ファイナライゼーションは専用のスレッドで行います。これらのサイクルは適切に管理されています。
静的にコンパイルされ、Adoroidランタイムに統合され、さらにガベージコレクタを持つRubyのランタイムをどのようにして実装したのか。私たちはHipByteのファンダであるLaurent Sansonetti氏に話を聞いた。
InfoQ:RubyMotionでは、Rubyのクラスは直接Javaのクラスにマップされ、ブリッジされていません。しかし、マシンコードにコンパイルされます。この仕組みについて詳しく教えてください。
AndroidのJava仮想マシンはJNIと呼ばれるC-レベルのAPIを公開しています。このAPIを使うとJava VMとCのコードを繋ぐことができます。Androidの世界では、これはNDKの一部です。
RubyMotionはRubyの静的コンパイルバージョンです。静的コンパイルによってRubyのコードはマシンコードに変換されます。Androidの場合、生成されたマシンのコードはJNI APIを呼んでJavaとのインターフェースになります。
このプロセスは新しいAndroidランタイムであるARTが行っていることと似ています。RubyMotionのアプリはマシンコードに事前コンパイルされますが、私が知る限り、ARTはデバイス上でコンパイルを行っています。
RubyのオブジェクトモデルはJava上で書き直されました。したがって、RubyからJavaへオブジェクトをブリッジしたり、コンバートしたり、変換したりする必要はありません。また、RubyのビルドインのコアクラスもJavaの対応するクラスをベースにしています(例えば、Arrayはjava.util.ArrayList
をもとにしています)。
InfoQ:コンパイル時にはRubyのめたプログラミングの特性はどのように処理していますか。
RubyMotionが提供するのはRubyのコンパイルバージョンであるという事実はメタプログラミングを制約しません。私たちはめたプログラミングAPIの完全なセットをサポートします。唯一の例外は#eval
です。というのは、アプリにインタプリンタを搭載していないからです(Appleのポリシーを守るためです)。
InfoQ:DalvikのGCを使っていますね。ネイティブコードによって確保されたメモリはどのように扱っていますか。
Rubyから生成したネイティブコードはDalvik(またはART)のGCを間接的に使います。従って、すべてのメモリは管理されています。ある種のオブジェクトの場合、ランタイムはマニュアルでメモリを確保するかもしれません。その場合は、finalize
メソッドが呼び出されたときに解放されます。
InfoQ:Ruby Gemsは使い続けられますか。
Android向けのRubyMotionにはいくつか制約があります。それは、iOSとOS Xと全く同じです。Rubyの静的コンパイルバージョンなので、#require
をサポートしないのです(すべてのファイルはビルド時に揃っていなければなりません)。そして、#eval
も実装されていません。それゆえ、通常のRuby gemsは動作しません。
RubyMotionは独自のバージョンのgemsを持っています。特別に設計されたものです。motion-toolbox.comはコミュニティによってメンテナンスされているリストです。
InfoQ: RubyMotionアプリの性能はどうでしょうか。JNIを使うと性能が劣化するということはありますか。
性能については何もしていません。しかし、テストはしています。その結果、この実装は、大きな性能上の劣化を伴わず、問題なく動作することを確認しています。JNIを呼ぶのはそれほど問題ではないようです。実際、多くのAndoridランタイムが同じレベルで書かれており、私たちと同じレベルでAPIを利用しています。
InfoQ: インタビューありがとうございました。
Android向けのRubyMotionはまだ利用可能ではないが、ベータテスターを探している。最終的なリリースは年末になりそうだ。
あなたは、Androidに移植したいRubyMotionで作ったiOSアプリはあるだろうか。それとも、Rubyでアプリ開発をしたいアンドロイド開発者だろうか。RubyMotion for Androidをどう思うだろう。