由于一个简单的原因,几乎不可能回答您的问题:没有几种方法,它们是一个连续体。这个连续体中涉及的实际代码也相当相同,唯一的区别是事情发生的时间,以及是否以某种方式保存了中间步骤。这个连续体中的各个点(不是一条线,一个级数,而是更多的具有不同角的矩形,您可以靠近这些点)是:
- 阅读源代码
- 理解代码
- 执行你所理解的
- 沿途缓存各种中间数据,甚至将它们持久保存到磁盘。
例如,一种纯解释型编程语言几乎不会做 #4 和 #2 有点隐式发生在 1 和 3 之间,所以你几乎不会注意到它。它只是读取代码的一部分,并立即对它们做出反应。这意味着实际开始执行的开销很小,但是例如在循环中,相同的文本行被读取并再次重新读取。
在矩形的另一个角落,有传统的编译语言,通常,第 4 项包括将实际机器代码永久保存到文件中,然后可以在以后运行。这意味着您在开始时要等待相当长的时间,直到整个程序被翻译(即使您只在其中调用一个函数),但 OTOH 循环更快,因为不需要再次读取源代码。
然后是介于两者之间的东西,例如虚拟机:为了可移植性,许多编程语言不会编译为实际的机器代码,而是编译为字节码。然后有一个编译器生成字节码,还有一个解释器获取这个字节码并实际运行它(有效地“将其转换为机器码”)。虽然这通常比编译并直接转为机器代码要慢,但将这种语言移植到另一个平台更容易,因为您只需移植通常用高级语言编写的字节码解释器,这意味着您可以使用现有的编译器来执行这种“有效地转换为机器代码”,并且不必为您要运行的每个平台制作和维护后端。还有,这可以如果您可以执行一次字节码的编译,然后只分发编译的字节码,那么速度会更快,这样其他人就不必花费 CPU 周期来例如在您的代码上运行优化器,而只需支付字节码到本机的费用翻译,在您的用例中可能可以忽略不计。此外,您没有分发源代码。
介于两者之间的另一件事是即时编译器(JIT),它实际上是一个解释器,它以编译的形式保存它曾经运行过的代码。这种“保留”使其比纯解释器慢(例如,增加的开销和 RAM 使用导致交换和磁盘访问),但在重复执行一段代码时使其更快。它也可以比纯代码编译器更快,例如只重复调用一个函数,因为如果不使用它,它不会浪费时间编译程序的其余部分。
最后,您可以在此矩形上找到其他位置,例如通过不永久保存已编译代码,而是再次从缓存中清除已编译代码。通过这种方式,您可以例如节省嵌入式系统上的磁盘空间或 RAM,但代价是可能不得不再次编译一段很少使用的代码。许多 JIT 编译器都这样做。