尽管 JRuby 的性能已经接近 CRuby 了,但有时它仍然不够快。CRuby 的用户可以使用 Ryan Davis 的 RubyInline 库,它提供了对 C/C++ 的内建支持以便更容易的产生 Ruby 的 C 扩展。来自 JRuby 阵营的 Charles Nutter 现在已经为 JRuby实现了一个RubyInline builder ,它可以即时编译嵌入的Java 代码。
下面是 Ryan Davis 提供的使用 C 编写的一个阶乘计算方法的示例:
<pre id="g.ip">class MyTest<br id="gg56"></br> inline do |builder|<br id="a5to"></br> builder.c "<br id="o7i9"></br> long factorial_c(int max) {<br id="dj:h"></br> int i=max, result=1; <br id="rnt4"></br> while (i >= 2) { result *= i--; } <br id="j64w"></br> return result; <br id="xb.3"></br> }<br id="vq68"></br> "<br id="b7z2"></br> end<br id="d2ex"></br>end
下面是 Charles 提供的相应的 JRuby 实现 :
<pre id="lj9x">class FastMath<br id="eg5a"></br> inline :Java do |builder|<br id="tt6-"></br> builder.package "org.jruby.test" <br id="ewoj"></br> builder.java "<br id="s-qc"></br> public static long factorial_java(int max) {<br id="k56e"></br> int i=max, result=1;<br id="kbyq"></br> while (i >= 2) { result *= i--; } <br id="fj21"></br> return result; <br id="wt2c"></br> }<br id="a3:d"></br> "<br id="uf-w"></br> end<br id="fu0o"></br>end
RubyInline for JRuby 的一个缺点在于其需要 Java 6 JDK(对于编译器),它可能还无法在所有系统上都可使用。
另一个可产生快速执行代码的方法就是直接产生 JVM 字节码。对于正常的应用来说,这听起来有些过激了,像编译器这样的字节码生成工具会从一个简单的字节码生成DSL 中获益,就像早前Charles Nutter 的博客中提到的那样。然而即便通过DSL 来生成字节码也并非易事。以下是 Charles 的博客中的一个例子:一个名为 bar 的方法将小写的 String 参数加到传进来的 ArrayList 中,下面就是产生的代码:
<pre id="fp3l">def test_class_builder<br id="e2jl"></br> cb = Compiler::ClassBuilder.build("MyClass", "MyClass.java") do<br id="d0-g"></br> [...] <br id="q2k4"></br> method(:bar, ArrayList, String, ArrayList) do<br id="jifn"></br> aload 1 <br id="w:4j"></br> invokevirtual(String, :toLowerCase, String) <br id="psay"></br> aload 2 <br id="a-lu"></br> swap<br id="qomp"></br> invokevirtual(ArrayList, :add, [Boolean::TYPE, Object]) <br id="n5w8"></br> aload 2 <br id="h.os"></br> areturn<br id="xg21"></br>end<br id="vw.6"></br>[...]
Charles Nutter 还提供了一个新方案,这就是叫做 Duby 的新语言,它实现了 Ruby 语法的一个子集,增强了一些类型推断逻辑(请访问 Charles 的博客来了解更多信息),以此来生成快速的字节码。下面同样是计算阶乘的方法,这次是针对 Duby 编译器而写的。
<pre id="ggl8">class Fac<br id="wnkw"></br> def self.fac(max)<br id="t858"></br> {max => :int, :return => :int}<br id="vd8-"></br> i = max<br id="cknn"></br> result = 1<br id="f1k-"></br> while i > 1<br id="ioqm"></br> result *= i<br id="upkk"></br> i -= 1 <br id="pg:2"></br> end<br id="iho3"></br> result<br id="yd-t"></br> end<br id="pn6r"></br>end
这是一个原型,用来展现以一种类 Ruby 语言而不是一种新语言来实现类型推断的可能性。它还可被 JRuby 程序员所用,以避免因为性能问题而回退到 Java,或者用来实现 JRuby 本身的一些部分功能,这与 Squeak Smalltalk 的 Slang 很像,它是 Smalltalk 语言的一个子集,可以很轻易的转化为 C。Rubinius 计划使用叫做 Garnet(InfoQ已经就Cuby/Garnet 采访了Evan Phoenix )的类似方法。
现在,对于JRuby 来说,你想使用何种代码生成方式呢?
查看英文原文: Using JRuby to generate Code for the JVM - - - - - -
译者简介:张龙,同济大学软件工程硕士,现就职于理光软件研究所。主要从事文档工作流和办公自动化解决方案的研发工作。热衷于 Java 轻量级框架的研究,对敏捷方法很感兴趣。曾有若干年的 J2EE 培训讲师经历。参与 InfoQ 中文站内容建设,请邮件至 china-editorial[at]infoq.com 。
评论