好的,首先,我不想在这里或类似的东西。我的更大的问题是理论上的,它将包括很少的示例。

因此,正如我写的那样,我不明白解释语言如何有效。而且由于它的现代,我将以Java为例。

让我们回到没有JIT编译器的日子。 Java的虚拟机基本上是其硬件。您编写代码,比将至少从虚拟机上摘取一些工作的字节码中的代码,这很好。但是,考虑到硬件中RISC指令集的复杂程度,我什至无法想到在软件模拟硬件上进行操作的方法。

我没有编写虚拟机的经验,所以我不知道它在最有效的水平上是如何做到的,但是我想不出比测试比赛ADN的每一个指令比采取适当的动作更具效率的。你知道,类似: if(instruction=="something") { (do it) } else if(instruction=="something_diffrent"){ (do it) }ETC....

但这必须非常慢。尽管如此,即使有一些文章,Java在JIT编译器之前也很慢,他们仍然说它并不那么慢。但是,要模拟它必须需要许多真实HW的时钟周期才能执行一项字节码指令。

尽管如此,即使整个平台也基于Java。例如,Android。 Android的第一个Verisons没有JIT编译器。他们被解释了。但是不应该比android慢慢慢吗?但事实并非如此。我知道,当您调用某些API函数,从Android库中,它们是用机器代码编写的,因此它们效率很高,因此很有帮助。

但是,想象一下,您将使用仅显示图像的API来编写自己的游戏引擎。您需要进行许多数组复制操作,许多计算在模拟时会非常慢。

现在正如我所承诺的一些例子。由于我主要与MCUS合作,因此我找到了Atmel Avr MCU的JVM。 Thay指出,8MHz MCU每秒可以进行20K Java Optcodes。但是,由于AVR可以在一个或两个周期中执行大多数说明,因此可以说平均6000000个说明。这使我们认为,没有JIT编译器的JVM速度慢了300倍。那么,为什么没有JIT编译器就会变得如此受欢迎呢?这不是太糟糕的性能损失吗?我只是听不懂。谢谢。

有帮助吗?

解决方案

我们已经有很长时间的字节代码了。在旧的Apple II上,USCD P-System非常受欢迎,该系统将Pascal汇编为字节代码,该代码将由可能以2 MHz运行的8位6502来解释。这些程序确实很快运行。

字节码解释器通常基于跳台,而不是一条链 if/then/else 语句。在C或C ++中,这将涉及 switch 陈述。从根本上讲,解释器将等同于一系列处理代码,并将字节代码指令中的OpCode用作数组的索引。

也可以具有比机器指令更高级别的字节代码,因此一个字节代码指令将转化为几个,有时是许多机器代码指令。为特定语言构建的字节代码可以很容易地执行此操作,因为它只需要匹配该特定语言的控制和数据结构。这扩展了开销的解释,并使口译员更有效。

与汇编的语言相比,解释的语言可能会受到一定的速度罚款,但这通常并不重要。许多程序以人类的速度处理输入和输出,这会浪费大量的性能。即使是网络结合的程序也可能具有可用的CPU功率要多得多。有些程序可以使用它们可以获得的所有CPU效率,出于明显的原因,它们往往不用解释的语言编写。

而且,当然,有一个问题是,您可能会或可能不会有所作为的效率可能会有所作为。解释的语言实现往往比编译实现更容易端口,并且实际的字节代码通常是可移植的。将更高级别的功能放在语言中可能会更容易。它允许编译步骤短得多,这意味着执行可以更快地启动。如果出现问题,它可以允许更好的诊断。

其他提示

但是不应该那么慢慢地慢慢来吗?

定义“非常慢”。这是电话。在您拨打第二位数之前,它必须处理“拨号数字”。

在任何交互式应用中,限制因素始终是人类反应时间。它可能会慢100次,并且仍然比用户快。

因此,为了回答您的问题,是的,口译员通常很快,但它们通常足够快,尤其是随着硬件越来越快。

请记住,当引入Java时,它是作为网络小程序语言出售的(替换并替换为JavaScript--也解释了)。只有在JIT编译之后,它才在服务器上流行。

字节码解释器可以通过使用跳台表:IF()s的行更快:

 void (*jmp_tbl)[256] = ...;  /* array of function pointers */
 byte op = *program_counter++;
 jmp_tbl[op]();

有两种不同的方法可以解决这个问题。

(i)“为什么可以运行慢速代码可以”

正如詹姆斯上面已经提到的那样,有时并不是您感兴趣的执行速度。对于以解释模式运行的许多应用程序可能“足够快”。您必须考虑如何使用您编写的代码。

(ii)“为什么解释的代码无缺乏”

您可以通过多种方法来实现口译员。在您的问题中,您谈论了最幼稚的方法:基本上是一个很大的开关,可以在阅读时解释每个JVM指令。

但是您可以优化:例如,您可以查看它们的序列,而不是查看单个JVM指令,并查找具有更有效解释的模式。 Sun的JVM实际上在解释器本身中进行了一些优化。在上一份工作中,一个人花了一些时间以这种方式优化解释器,并解释了Java字节码在更改后运行速度更快。

但是在包含JIT编译器的现代JVM中,口译员只是垫脚石,直到JIT完成工作,因此人们并没有花那么多时间优化口译员。

12 MHz将是一个Attiny,它是8位微处理器。这意味着(例如)本机添加“指令只能将两个8位编号添加在一起以获得9位结果。JVM基本上是一个虚拟的32位处理器。这意味着其添加指令添加了两个32--位数在一起以产生33位结果。

因此,当您比较指令率时,您应该期望将指令率降低4:1的绝对最低限度。实际上,虽然很容易模拟带有4个8位添加的32位添加(带有携带),但有些事情并非如此。例如,根据Atmel自己的 应用注释, ,产生32位结果的16x16乘法在〜218时钟周期中执行。相同的应用注释显示了以255个周期运行的16/16位除外(产生8位结果)。

假设有线性的刻度,我们可以预期32位版本的乘法将进行〜425-450的时钟周期,而划分〜510循环。实际上,我们可能应该期待一些开销,这将降低速度更多 - 将这些估计值至少增加10%可能会使它们更现实。

最重要的是:当您将苹果与苹果进行比较时,很明显,您所说的很多速度差异根本不是真实的(或者无论如何都不可归因于JVM开销)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top