将Ruby转换为低级语言?

15

我使用Ruby进行各种脚本编写:

rails (symfony)
ruby (php, bash)
rb-appscript (applescript)

能否用 Ruby 替代低级语言?

我用 Ruby 写代码,然后它会转换成 Java、C++ 或 C 语言。

一些人说,在 Ruby 中处理性能更敏感的任务时,你可以用 C 扩展 Ruby。但是“扩展”意味着编写 C 文件,然后在 Ruby 代码中调用。我想知道,是否可以使用 Ruby 并将其转换为 C 源代码,然后编译为机器码。那么我就可以在 Ruby 代码中“扩展”它,而不是用 C 来实现。

这就是本帖讨论的内容。用 Ruby 编写所有代码,但获得与 C(或 Java)相同的性能。

第二个好处是您不必学习其他语言。

就像 PHP 的 HipHop 一样。

是否存在这样的实现方式?


4
Khm,Java和C#并不是低级语言 :) - Nikita Rybak
4
尼基塔说:“艾伦·佩利斯说过,“当编程语言的程序需要关注无关紧要的内容时,它是低级的。”作为一个多年使用Java和C#以及其他低级和高级语言编写代码的人,我确实将这两种语言称为低级语言。(C#4 也许已经接近高级语言的门槛了,但它变得如此复杂,需要关注其复杂性本身可能导致它无法符合佩利斯标准,在我看来。) 对于程序员来说,每次需要lambda函数就重新实现它们是否真的相关呢? - Ken
1
@Ken 我曾经认为高级语言是让你不需要了解计算机和它的工作细节的语言。从这个意义上说,函数式、过程式和面向对象的语言都可以是高级语言。即使是非常复杂的语言(比如Ada),也仍然可以是高级语言。至于Alan Perlis所说的这句话有点含糊不清,没有上下文很难确定他的意思。 - Nikita Rybak
Nikita:我同意函数式、过程式和面向对象语言可以是高级语言,我已经使用了所有这些语言的好例子。但我仍然不能一本正经地说“Java是一种高级语言”。 :-) - Ken
7个回答

14

这样的编译器将是一项巨大的工作。即使它能够工作,它仍然需要:

  1. 包含 Ruby 运行时
  2. 包含标准库(该库不是为了性能而构建,而是为了可用性)
  3. 允许元编程
  4. 进行动态分派
  5. 等等。

所有这些都会对运行时造成巨大的惩罚,因为 C 编译器既不能理解也不能优化这样的抽象。Ruby 和其他动态语言不仅因为它们是解释性的(或者编译成字节码后再解释),而且还因为它们是动态的,所以它们更慢。

示例

在 C++ 中,大多数情况下可以内联方法调用,因为编译器知道 this 的确切类型。如果传递了子类型,则方法仍然无法更改,除非它是虚拟的,在这种情况下,仍然使用非常高效的查找表。

在 Ruby 中,类和方法可以随时以任何方式更改,因此每次都需要进行(相对昂贵的)查找。

像Ruby、Python或Perl这样的语言有许多功能是非常昂贵的,大多数相关程序都严重依赖这些功能(当然,它们非常有用!),因此不能被删除或内联。

简单来说:动态语言很难进行优化,仅仅做一个解释器所做的事情并将其编译成机器代码是不够的。像V8一样,可以从动态语言中获得惊人的速度,但你必须投入巨额资金和充满聪明程序员的办公室。


2
@Dorian,我两年前写的话仍然是正确的。JIT编译器可以规避我提到的一些问题,但这并不意味着这些问题不重要。AOT编译,也就是这个问题和我的回答所涉及的内容,仍然且永远无法有效地优化动态语言。 - user395760
现在有一个实验性的"Sorbet Compiler",可以从Ruby代码生成本地扩展。 - Anderson Green

12

有一个Ruby To C编译器,它只接受Ruby的一个子集。我认为主要缺失的部分是元编程功能。


它是一个将Ruby转换为C的转换器,然后将C源代码编译成二进制文件的工具吗? - never_had_a_name
1
Ruby2c的链接已经失效,但我已经开始了一个相似的项目,目的相同。链接在这里:https://github.com/jarble/transpiler - Anderson Green
链接不再可用。 - Jonathan Komar
1
我认为这是Github上相同的项目:https://github.com/seattlerb/ruby_to_c - Redoman
@AndersonGreen 它支持哪种语言?从存储库自述文件中看,它似乎目前只能将JavaScript转译为Java? - Redoman
@jj_ 它可以将JavaScript、Ruby、PHP和其他几种语言的一个小子集转换成Java。目前的实现非常缓慢,因此我不建议立即使用它。 - Anderson Green

10

在最近的一次采访中(2012年11月16日),Ruby的创建者Yukihiro“Matz”Matsumoto谈到了将Ruby编译成C语言的事情。

(......)在东京大学,一位研究生正在进行一个学术研究项目,该项目在编译二进制代码之前将Ruby代码编译为C语言代码。这个过程涉及到类型推断等技术,在最优化的情况下,速度可以达到手写C代码的90%。目前只发表了一篇论文,没有公开源代码,但我希望明年一切都会揭晓......(来源于采访)

虽然只有一名学生,但这可能是一个有趣的项目。也许还需要很长的路才能完全支持Ruby。


现在是2017年!项目发生了什么事? - Anwar
2
@Anwar 最有可能的?现实。 - DepressedDaniel

5
“低级”这个概念非常主观。很多人会有不同的划分标准,因此为了方便讨论,我假设你的意思是编译Ruby成一个中间形式,然后将其转换成你特定平台的机器码。也就是说,将Ruby编译成C或LLVM IR等形式。
简短的回答是可以的。
更详细的回答如下:
有一些语言(最显著的是Objective-C)作为其他语言的薄层存在。实际上,ObjC语法只是objc_*() libobjc运行时调用的一个松散包装器。
知道了这点,那么编译器会做什么呢?它基本上像任何C编译器一样工作,但还会处理objc特定的内容,并生成适当的C函数调用以与objc运行时交互。
Ruby编译器可以采用类似的方式实现。
然而,需要注意的是,仅仅将一种语言转换为较低级别的形式并不意味着该语言会立即表现得更好,尽管也不意味着它会表现得更差。你真的必须问问自己为什么想这样做,以及是否有充分的理由。

@jer。有人说,当涉及到 Ruby 中的更重要的性能任务时,可以使用 C 扩展它。但是扩展这个词意味着你要编写 C 文件,然后在 Ruby 代码中调用它们。我想知道,是否可以使用 Ruby 并将其转换为 C 源代码,然后将其编译成机器代码。然后我就可以在 Ruby 代码中“扩展”它,但可以获得 C(或 Java)的性能。这就是这篇文章的主旨。以 Ruby 写所有内容,但获得 C (或 Java)的性能。 - never_had_a_name
3
任何编译器都需要非常聪明,才能让生成的代码和一个熟练使用目标语言的程序员写的扩展一样有效。现在的C/C ++编译器非常聪明,因此它们在90%的情况下击败了90%的汇编程序员,但是他们经过了数百年的发展,并得到了许多大公司的支持才取得了如此成就。但是,任何Ruby到C的编译器,在开源组织可能在10年内制作出来,仍然会落后于编写良好的C代码。 - user395760
@ajsie:在第一个上下文中,您所说的“extend”的意思是我们语言专家倾向于称之为“bind”。此外,在第二个实例中,“extend”被称为“FFI”。Ruby确实提供了绑定,但没有内置的FFI(不过有相关库),这将使您能够与C代码进行交互。 - jer
@jer:我现在太累了,没有精力再仔细检查(德国这里已经快凌晨4点了,我刚从长达8小时的繁重工作回到家),但我认为从Ruby 1.9.2开始,FFI已成为标准库的一部分。 - Jörg W Mittag
@Jörg:说实话,那很有可能。我还没有太关注 1.9 分支的情况。Ruby 不再是我主要开发的语言了,所以有时候很难抽出时间跟上新的发展趋势。 - jer
如果将Ruby转换为C并获得显着的性能改进很容易,那么你就不需要这样做,因为Ruby的开发者们已经在正常运行时中完成了这个工作。它变得更快的原因是因为C的语义非常不同:带溢出的fixints、没有异常、函数调用在编译时被固定等等。手动转换为C之所以奏效,是因为它强制程序员进行巨大的简化假设,这些假设在Ruby语法中无法表达。 - Ken

3

如果您仍然认为Java是一种低级语言,也可以考虑JRuby。实际上,这里与语言本身关系不大:可以编译成JVM字节码,这是与语言无关的。


你认为通过“使用C/Java扩展Ruby”这个方法,能够解决人们所关注的性能问题吗? - never_had_a_name
你在这里不是扩展(不将其他语言的功能添加到现有的Ruby代码中),而是在不同的虚拟机中运行代码。是的,据说JRuby比MRI(ruby 1.8的虚拟机)运行得更快。然而,还有一些其他的Ruby VM实现,1.9.1承诺更快。我自己没有进行基准测试,但你可以搜索一些不同Ruby实现速度的比较。 JRuby是最快的之一。 - Chubas

3
性能不仅仅来自于“低级”编译语言。将Ruby程序交叉编译为复杂的自动生成的C代码也不会有所帮助,反而可能会使事情更加混乱,包括长时间的编译等待。事实上有更好的方式。
但是你先说“低级语言”,然后提到Java。 Java不是一种低级语言。它在高或低级语言方面仅比Ruby低一个级别。但是如果您观察Java的工作方式,JVM、字节码及即时编译,您可以看到高级语言如何变得更快。目前Ruby正在做类似的事情。MRI 1.8是一种解释性语言,存在一些性能问题。1.9则快得多,它使用了字节码解释器。我不确定它是否会在MRI上实现,但Ruby距离JIT只有一步之遥。
我不确定jRuby和IronRuby背后的技术,但它们可能已经在做此操作。但是,两者都有自己的优点和缺点。我倾向于使用MRI,它足够快,并且工作得很好。

0

设计一个将Ruby源代码转换为C++的编译器可能是可行的。可以使用unholy编译器将Ruby程序编译为Python,因此可以使用Nuitka编译器将其从Python编译为C++。

unholy编译器开发已有十多年,但它可能仍然适用于当前版本的Python。

Ruby2Cextension是另一种编译器,它将Ruby的子集翻译成C++,尽管自2008年以来没有更新过。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接