JRuby生成JVM代碼詳解
盡管JRuby的性能已經(jīng)接近CRuby了,但有時它仍然不夠快。CRuby的用戶可以使用Ryan Davis的RubyInline庫,它提供了對C/C++的內(nèi)建支持以便更容易的產(chǎn)生Ruby的C擴展。來自JRuby陣營的Charles Nutter現(xiàn)在已經(jīng)為JRuby實現(xiàn)了一個RubyInline builder ,它可以即時編譯嵌入的Java代碼,即使用JRuby生成JVM代碼。
下面是Ryan Davis提供的使用C編寫的一個階乘計算方法的示例:
- class MyTest
- inline do |builder|
- builder.c "
- long factorial_c(int max) {
- int i=max, result=1;
- while (i >= 2) { result *= i--; }
- return result;
- }
- "
- end
- end
下面是Charles提供的JRuby生成JVM代碼的實現(xiàn) :
- class FastMath
- inline :Java do |builder|
- builder.package "org.jruby.test"
- builder.java "
- public static long factorial_java(int max) {
- int i=max, result=1;
- while (i >= 2) { result *= i--; }
- return result;
- }
- "
- end
- end
RubyInline for JRuby的一個缺點在于其需要Java 6 JDK(對于編譯器),它可能還無法在所有系統(tǒng)上都可使用。
另一個可產(chǎn)生快速執(zhí)行代碼的方法就是直接使用JRuby生成JVM代碼。對于正常的應用來說,這聽起來有些過激了,像編譯器這樣的字節(jié)碼生成工具會從一個簡單的字節(jié)碼生成DSL中獲益,就像早前Charles Nutter的博客中提到的那樣。然而即便通過DSL來生成字節(jié)碼也并非易事。以下是Charles的博客中的一個例子:一個名為bar的方法將小寫的String參數(shù)加到傳進來的ArrayList中,下面就是產(chǎn)生的代碼:
- def test_class_builder
- cb = Compiler::ClassBuilder.build("MyClass", "MyClass.java") do
- [...]
- method(:bar, ArrayList, String, ArrayList) do
- aload 1
- invokevirtual(String, :toLowerCase, String)
- aload 2
- swap
- invokevirtual(ArrayList, :add, [Boolean::TYPE, Object])
- aload 2
- areturn
- end
- [...]
Charles Nutter還提供了一個新方案,這就是叫做Duby的新語言,它實現(xiàn)了Ruby語法的一個子集,增強了一些類型推斷邏輯(請訪問Charles的博客來了解更多信息),以此來生成快速的字節(jié)碼。下面同樣是計算階乘的方法,這次是針對Duby編譯器而寫的。
- class Fac
- def self.fac(max)
- {max => :int, :return => :int}
- i = max
- result = 1
- while i > 1
- result *= i
- i -= 1
- end
- result
- end
- end
這是一個原型,用來展現(xiàn)以一種類Ruby語言而不是一種新語言來實現(xiàn)類型推斷的可能性。它還可被JRuby程序員所用,以避免因為性能問題而回退到Java,或者用來實現(xiàn)JRuby本身的一些部分功能,這與Squeak Smalltalk的Slang很像,它是Smalltalk語言的一個子集,可以很輕易的轉化為C。Rubinius計劃使用叫做Garnet(InfoQ已經(jīng)就Cuby/Garnet采訪了Evan Phoenix)的類似方法。
現(xiàn)在,你應該知道使用JRuby生成JVM代碼的好處了。
【編輯推薦】