7月に、GE Energy Management( GE Energyが7月に分割された) 時にできた)内の Digital Energy部は、Smalltalkに触発されたプログラミング言語、Magikを彼らに独占所有権のある仮想マシン MagikSFからJVMへ移植中であることを明らかにした。
Magikは動的型付けのオブジェクト指向言語であり、多重継承とポリモフィズムをサポートしている。Java以前に遡り、元々1990年に発表された。 GE EnergyのSmallworld 技術プラットフォームで使われ、電力配給と電気通信のような企業ユーティリティ向けの複雑なアプリケーションを実装するために設計されていた。例えば電気通信ドメインでは、GE Energy Management は、 Physical Network Inventoryと呼ばれる製品を持っており、これによって、電気通信会社は、銅、光ファイバ、ケーブル通信ネットワークを計画、管理できる。ユーティリティ側では、 Electric Officeが同様な機能を電力配給会社に提供している。
言語はRubyに非常に似た感じである。以下に簡単な "hello world"の例を示す。
Magik> _for i _over 1.upto(3)
_loop
write("Hello world ", i)
_endloop
Rubyではこのようになる
1.upto(3) do |i|
puts("Hello world #{i}")
end
両方の出力は、こうなる。
Hello world 1
Hello world 2
Hello world 3
移植が公開されたのは今年の7月であるが、GE Energy チームは、1年前の2011年7月に概念証明を始めており、小さなチームがJava 7の早期リリース版で開発していた。チームのリーダーでアーキテクトである George Marrows氏がInfoQに以下のように話した。
これは非常に成功しました。我々はその時から製品リリースを目指して開発してきました。我々はMagik言語用のパーサー、コンパイラー、ランタイムを書き、我々のCライブラリのほとんどを統合し、Java2Dを使って、完全に新しいグラフィクスサブシステムを書きました。全てが既存システムとの互換性において、非常に高いレベルに達しています。
それは未だ完成していないが、移植されたバージョンは全アプリケーションを走らせることができる。批判的には、 GE Energyのパートナーや顧客が書いた何百万行のMagikコードを考えると、移植は MagikSFバージョンと完全な互換性を目指して、開発者はJVM移植版上でMagikソースコードを簡単に再コンパイルできる。「我々は自信を持って言えるのは、我々の言語実装は極めて MagikSFのものに近く、我々のライブラリサポートも非常に良く、既存のMagikコードをもっと多く走らせることで、常に改善しており、あらゆる非互換性を修正しています。」とMarrowsが我々に言った。
Magikの動的型システム鑑みて、予想されるように、移植版はJava 7の invokedynamicバイトコード命令を多用している。氏が言うには,
我々は物凄く invokedynamicを使ってますが、一番多いのはメソッドディスパッチにですが、複雑なリテラルを使われる場所にバインドするためにや、グローバル変数を解決するのにも使っています。 Duncan MacGregor氏がこの件をチーム内で責任をもって行ってきました。一つ言いたいのは、彼は invokedynamicを非常に良く使って、毎週新しいパフォーマンス改善を発見したようです。
invokeDynamic と java.lang.invokeを使った経験は、大変素晴らしいです。これに対する1つの考え方は、 機能をインライン化する、JVM JITコンパイラーのメソッドに対するAPIであり、この考えは非常にうまく行く。我々が喜びながら驚いたのは、昨年Java 7の最初のリリース以来、アップデートの度に、著しいパフォーマンス改善が見られたことです。Java 8の「ラムダ式」の成果から更に改善が得られるようです。
技術的な観点から、 JVMには、MagikSFではサポートされない幾つもの機能があります。例えば、
- MagikSFはインタプリタ型ですが、JVMはJITコンパイルを提供している
- MagikSFはグリーンスレッドを使っているが、JVMにはネイティブスレッドがある
- MagikSFは32ビットのみだが、JVMは64ビットもサポートしている
- MagikSFは独自のガーベッジコレクションを持っていて、世代型であるが並列でない。Javaは複数のGC選択肢を提供しており、Hotspotでほとんど並列なコレクションがサポートされている
もちろん、JVMの開発にはかなりのリソースが要り、 Oracle や IBMのような大きなソフトウェアベンダーがそのプラットフォームに専門家を充てることができる。
Marrowsのチームが達成したパフォーマンス改善の結果は、感動的である。Java移植版の方が既にチームが行ったベンチマークテストの大部分で早く、幾つかのケースでは30倍に達した。 Marrows氏が注意したのは、パフォーマンス改善は、invokeDynamic とJVMが時間とともに改善されたことによることだ。 Java 7 update 9の方が Java 7 update 2より改善されているなど。もっと著しく、OracleはJava 8のラムダプロジェクトの一部として、invokeDynamicを書き直した。このバージョンはJava 7にバックポートされる(今度の update 12に含まれる予定だ)。この新バージョンは多くの場合にかなり速くなっている。 Marrows氏は、幾つかのコード例では update 9と比べて update 12の現在のテストビルドのほうに、パフォーマンス劣化がある、と言っていた。彼らはこのことをOracleのチームと議論することになっている。チームはこれまで、Oracle特に JSR 292専門家グループの Remi Forax氏から多大なサポートを得ているが、彼は「我々が JSR 292に取りかかるのを助けてくれ、そしてMLVM (multi-language virtual machine) メーリングリストへの精力的なコントリビュータである。」
プロジェクトの最初の計画にはなかったが、チームはまた、 JNI と Java 2Dを合わせてグラフィックスシステムの移植を行なっている。「JNIはCライブラリと統合するためで、我々のデータベースへのアクセスを提供し、最適化された幾何学と他の計算を行う。Java 2Dは地図とUIのレンダリングを行う。」
チームはかなり上手く、JavaからMagikへ行くための自家製内部関数を作り上げた。これは、新しいJava 2Dベースのグラフィックスシステムで多用されている。
def_slotted_exemplar(
:line_style,
{ { :colour, colour } },
{ :simple_style_mixin},
{:|com.gesmallworld.magik.commons.drawingsurface.LineStyle|})
$
_private _method line_style.|getColour|()
>> .colour
_endmethod
getColour| の縦棒はJava用に大文字/小文字を保持するために使われている。Magikでは大文字小文字の区別は無いからである。
Magik からJavaへの内部関数は、ちょっと手間がかかる。開発者がラッパーコードを書く必要があるからだ。
public class Char16Vector {
@MagikInitialiser
public static void exposeThisClass() {
//Expose an instance of this class to Magik
}
@MagikMethod(name="nth()")
public Char16Vector nth( Integer index ) {
return new Char16Vector(value.substring(index-1, index));
}
}
Oracleの新しいJavaScript実装のNashornは、動的リンクライブラリを使って、ずっと綺麗にこのことができる。 Jim Laskey氏が彼のブログで、これがいかに上手く動くかの良い例 を提供しているが、Twitter4Jライブラリを使ってTwitterに話すために Nashornを使っている。
Java仮想マシンへのアクセスと同様に、チームはJavaプラットフォーム上で動くことによる、他のいくつかの利点を見出している。JavaOne Brazilでのスピーチで、Marrows 氏はJava開発者とJavaライブラリの両方へのアクセスについて話した。更に彼が我々に話したのは、
...我々は、今後我々が行うあらゆる改善をサポートしてくれるJVMのパワーと柔軟性に、非常に感謝しています。
もっと一般的には、我々が今日まで開発してきた MagikSF環境の幾つかの部分を簡単化し、置き換える機会を持てました。例えば、グラフィックスサポート、ファイルI/Oなど。我々は今後、これをもっとやって行きたい、と考えています。
Magikは、 Groovy, JRuby 、Nashornを含む増え続ける言語の1つで、JVM上でinvokeDynamic を利用している。 JSR 292は本当に、JVMをプログラミング言語の普遍的な環境にする助けになっている。