最近开始学习V8 Javascript引擎,这篇文章是翻译官方文档的,解释了V8之所以快的主要原因等,原文请参见http://code.google.com/apis/v8/design.html。 V8是一个新的为了提高Javascript程序速度的Javascript引擎,在多项测试中,V8的速度比JScript (in Internet Explorer), SpiderMonkey (in Firefox), and JavaScriptCore (in Safari)都要快很多倍,如果你的JS网络应用程序正受制于JS引擎的速度,那么使用V8而不是你现在使用的JS引擎将可以大幅改善你的应用程序的表现。至于提升的幅度则由JS所占的比例以及JS的结构(nature of JS)等多方面因素决定,例如,如果一个函数在你的应用中将会被一次次重复运行,那么提升的幅度将会比很多函数都在你的应用中只运行一次要大很多,至于会这样的原因将会在后面的文章中解释。 V8速度提升的三个主要方面为:
快速的属性访问JS是一种动态语言,对象的属性(property)可以在运行时被动态的添加和删除,这意味着对象的属性很有可能被改变,绝大多数JS引擎采用一个字典型的数据结构来存储对象的属性,每一次属性的访问都需要一次动态的查询以获得属性在内存中的位置,这样的访问方法使得JS中的属性访问要比普通编程语言例如Java和Smalltalk中的对象访问要慢很多,在这些(普通的)编程语言中,对象的属性值根据类的固定结构,被编译器放在离对象指针有固定的偏移值的内存位置上,属性的访问只是一次简单的内存读取和写入,通常只需要一个(汇编)指令。 为了减少访问JS属性的时间,V8没有采用动态查询的方式,V8会在背后动态的创建隐藏类,在V8中,当对象的属性改变时,对象会更改隐藏类的指向。这种方式的基本思想并不是被创新出来的,在prototype-based的编程语言Self中也做了类似的事情,详见An Efficient Implementation of Self, a Dynamically-Typed Object-Oriented Language Based on Prototypes。 我们通过举例来更加清楚的了解整个过程。请看下面这个很简单的JS函数。
当new Point(x, y)被执行的时候,一个新的Point对象会被创建,当V8第一次执行这个函数的时候,V8会为Point创建一个初始的隐藏类,为方便,我们假设这个类叫C0,显然这个类里面什么都没有,这个时候,Point这个对象的隐藏类是C0。 当执行Point中的第一个语句(this.x = x;),会在Point对象中创建一个新的属性x,对于V8而言,会做如下事情:
当执行Point中的第二个语句(this.y = y;)的时候,将会在Point对象中创建一个新的属性y,对于V8而言,会做如下事情:
每次有一个属性被添加的时候就要重新创建一个隐藏类的做法看起来好像很低效,但是,因为类转移的存在,隐藏类可以被复用(如我上面所解释)。尽管JS比其他面向对象的编程语言都要更加动态,但是采用上面的方法,通过观察很多JS程序的运行,它们在很大程度上都重用了之前的结构(the runtime behavior of most JS programs results in a high degree of structure-sharing using the above approach). 利用隐藏的方法有两个好处:属性的访问不再需要一个字典查询,同时可以让V8使用一些在以类为基础的普通编程语言中可以用的优化方法,例如inline caching(参考 Efficient Implementation of the Smalltalk-80 System)。
|
|