Javascript引擎的优点
我现在对JavaScript引擎感到困惑。 我知道V8是一个大问题,因为它将JavaScript编译为本机代码。
然后我开始阅读关于Mozilla SpiderMonkey的信息 ,从我的理解是用C编写的,并且可以编译JavaScript。 那么这和V8有什么不同?如果这是真的,为什么Firefox不这样做?
最后, 犀牛是否真的将JavaScript编译为Java字节码,以便获得Java的所有速度优势? 如果没有,为什么人们在桌面上编写脚本时不能运行V8?
JavaScript执行有多种方法,即使在执行JIT时也是如此。 V8和Nitro(以前称为SquirrelFish Extreme)select做一个全方法的JIT,这意味着他们在遇到脚本时将所有JavaScript代码编译成本机指令,然后简单地执行,就好像它是编译的C代码。 SpiderMonkey使用了一个“追踪”JIT,它首先将脚本编译成字节码并解释它,但监视执行,寻找诸如循环之类的“热点”。 当它检测到一个时,它就编译这个机器代码的热门path,并在将来执行。
两种方法都有好处和坏处。 全方法JIT确保所有执行的JavaScript将被编译并作为机器代码运行,而不是被解释,一般来说应该更快。 但是,根据实现的不同,这可能意味着引擎花时间编译代码将永远不会执行,或者只能执行一次,而不是性能关键。 另外,这个编译的代码必须存储在内存中,所以这会导致更高的内存使用率。
在SpiderMonkey中实现的跟踪JIT可以生成极其专用的代码,因为它已经执行了代码,并且可以推测variables的types(例如将for循环中的索引variables当作本地整数),其中一个全方法的JIT将不得不把这个variables作为一个对象,因为JavaScript是无types的,并且types可以改变(如果假设失败,SpiderMonkey将简单地“脱离”跟踪,并返回到解释字节码)。 但是,SpiderMonkey的跟踪JIT目前无法在具有多个分支的代码上高效工作,因为跟踪针对单个执行path进行了优化。 另外,在决定编译一个跟踪之前,监视执行还有一些额外的开销,然后把执行切换到这个跟踪。 另外,如果追踪者做出了后来被违背的假设(如variables变化types),那么追踪和切换回解释的成本可能比使用全方法JIT更高。
V8是最快的,因为它把所有的JS编译成机器码。
SpiderMonkey(FF使用的)也是快速的,但是编译到一个中间字节码,而不是机器码。 这是与V8的主要区别。 编辑 – 较新的Firefox版本带有一个新的SpideMonkey变体; TraceMonkey的。 TraceMonkey可以对关键部分进行JIT编译,也可以进行其他智能优化。
Rhino将Javascript编译为Java类,从而使您可以基本上在Javascript中编写“Java”应用程序。 犀牛也被用作在后端解释JS并对其进行操作的方式,并具有完整的代码理解,如reflection。 例如YUI压缩机就是这样使用的。
之所以用犀牛来代替V8,可能是因为V8相对比较新,所以很多项目已经使用Rhino / Spidermonkey作为他们的JS引擎,例如Yahoo widgets。 (我想这就是你所说的“桌面上的脚本”)
编辑 – 这个链接也可以给一些SpiderMonkey被广泛采用的见解。 你会在你的应用程序中embedded哪个Javascript引擎?
如果你想看看各种浏览器中的Javascript引擎如何堆叠起来,安装Safari 4(是的,它现在也在Windows上运行!),Chrome V8,Firefox 3.5和IE 8(如果你在Windows上)并运行基准testing:
http://www2.webkit.org/perf/sunspider-0.9/sunspider.html
我相信正如上面的Pointy所说的那样,新的Firefox 3.5使用了TraceMonkey,它也使用某种forms的JIT编译到intermedit代码上。 所以它应该比V8略胜一筹。 至less它不会像Firefox 3 SpiderMonkey(没有JIT)那样比V8慢10倍。
对我来说… Safari 4.0.3在Win XP上比Firefox 3.5.3中的Tracemonky快2.5倍。 IE8要慢得多。 我目前没有安装Chrome。
不知道犀牛编译为java字节码。 如果它仍然可以解释Javascript的dynamic特性,比如能够在运行时为对象实例添加属性(例如obj.someNewAttribute =“someValue”,这是Javascript允许的)…我不太确定它是完全“编译的“字节码,而且除了每次运行Javascript时不必从Javascript源代码文本编译以外,您可能得不到更好的性能。 请记住,Javascript允许非常dynamic的语法,如eval(“x = 10; y = 20; z = x * y”); 这意味着您可以构build在运行时编译的代码string。 这就是为什么我认为即使你编译成JVM字节码,Rhino也会被混合模式解释/编译。
JVM仍然是一个解释器,尽pipeJIT支持非常好。 所以我喜欢将JVM上的Rhino作为2个解释器层(解释器解释器)或解释器^ 2。 而你的其他Javascript引擎大部分是用C编写的,因此应该更像解释器^ 1。 与C或C ++(参考Perl或Python或Ruby)相比,每个解释器层可以增加5-10倍的性能下降,但是使用JIT时,性能下降可能会低到2-4x。 JVM拥有迄今为止最强大和最成熟的JIT引擎之一。
所以你的里程会有所不同,如果你想在你自己的硬件和操作系统上想要一个真正的应用程序,你可能会从一些严重的基准testing中受益。
犀牛不能太慢,因为我知道很多人正在使用它。 我认为它的主要吸引力并不在于它的速度,而是易于编码/轻量级/可embedded/解释器与Java库挂钩,这使得它非常适合于软件项目的脚本/configuration/可扩展性。 一些像UltraEdit这样的文本编辑器甚至embedded了Javascript作为替代的macros脚本引擎。 每个程序员似乎都可以很容易地通过JavaScript,所以很容易接受。
犀牛的一个优势是它运行在JVM运行的任何地方。 根据我的经验,尝试使用独立的TraceMonkey或SpiderMonkey来从命令行构build和运行,对于像Windows这样的系统来说可能有些痛苦。 embedded到自己的应用程序可能会更费时间。 但是,如果您正在寻找一种可embedded的语言,那么为了一个大型的项目,回报是不值得的。
使用Rhino脚本非常简单,如果你有Java和犀牛jar,你只需编写你的javascript并从命令行运行它。 我一直用它来完成简单的任务。
为了回答这个问题,为什么本地代码V字节代码…
本机代码更快,谷歌的战略select,因为他们已经计划JS其中至less一个是ChromeOS。
关于这个问题的一个很好的video发布在Channel9上,在这里可以findV8后面的人Lars Bak的采访