我要学习Ruby。我知道这是一种解释性语言。我知道编译语言最终会被翻译成机器代码,但ruby解释器的作用是什么?我读到解释器是用C语言编写的,但是每一行ruby转换为c,它再次编译成机器代码?我也听说过JIT,但如果这给答案增加了很多复杂性,你就不需要回答这个问题了。我正在寻找的是我的Ruby代码会发生什么。
答案 0 :(得分:8)
它将Ruby代码转换为某种形式的更简单的“中间”表示(在最近的版本中,它编译为字节码)。它还在您的计算机内存中构建一个虚拟机,它模拟执行该表示的物理机器。
这台机器镜像物理机器,至少在合理和有用的范围内。它经常有一个用于指令的存储器,一个程序计数器,一个用于存储中间值和返回地址的堆栈等。一些更复杂的机器也有寄存器。有一个固定且相对原始的(与Ruby之类的语言相比,而不是与实际的CPU指令集相比)指令集。像CPU一样,虚拟机无休止地循环:
使用解释器,所有这些都通过间接层发生。你的实际物理CPU不知道它在做什么。 VM本身就是软件,上面的每个步骤都是委托给CPU的几个(在具有相当高级字节码指令的情况下,可能是几十或几百个)物理CPU周期。每次读取指令时都会发生这种情况。
输入JIT编译。最简单的形式只是将每个字节码指令替换为在解释器遇到它时将执行的代码(稍微优化)的副本。这已经使速度获胜,例如程序计数器操作可以省略。但是,甚至还有更聪明的变种。
例如,跟踪JIT作为常规解释器开始,并另外观察它们执行的程序。如果他们注意到程序在代码的特定部分花费了大量时间(几乎总是,循环或从循环中调用的函数),它会开始记录它在此期间的作用 - 它会生成跟踪。当它到达开始记录的点(循环的一次迭代之后)时,它会调用它一天并将跟踪编译为机器代码。但是由于它看到了程序在运行时的实际行为,它可以生成完全符合此行为的代码。以循环添加整数为例。机器代码不包含解释器实际执行的任何类型检查和函数调用。至少,它不会包含大部分内容。它将,为了确保正确性,添加检查记录跟踪的条件(例如所涉及的变量是整数)仍然成立。当这样的检查失败时,它会退出并重新开始解释,直到记录另一条跟踪。但在此之前,它可以以与手写C代码相媲美的速度执行一百次迭代。