warmhug

技术成长、工作感悟、教训反思

v8引擎初了解

chrome浏览器以“快速”著称于业界,其实都是v8引擎的功劳。这里偶然看到chrome官网介绍v8引擎的资料,抱着了解学习非研究的态度看了一看。幸好这资料够直白,对于我这个不搞也几乎完全不懂c++,但也想了解一下v8牛逼优点的人简直是莫大的恩惠呀。

本文并非完全翻译原文内容,而是把个人理解的文章主旨,并思考探索下这个优点能否运用在js方面,一并做介绍。闲话少说,正文开始…

v8的Design Elements(设计原理)中优秀的地方成就了其强大,它的特点是快,宣称其js执行速度是JScript (in Internet Explorer), SpiderMonkey (in Firefox), JavaScriptCore (in Safari)等引擎的好几倍。不过,是不是所有类型的js代码相对其他引擎都能执行的很快呢?当然不是。官方指出,如果js应用程序里有不少函数是需要重复执行的,那么其性能相对其他引擎就高很多;但是如果许多函数都是仅仅执行一遍,其表现并不比其他引擎好很多。现在的js应用程序越来越大,里边需要重复执行的函数,自然越来越多,v8引擎的优势就发挥出来了。接下来重点解释为什么会有这现象。
1、快速的属性访问
大多js引擎以字典(键值对)的数据结构存储属性,这样每次访问某个属性都要遍历查找到其内存中的相应位置,这样的访问速度是很慢的。V8不使用这种动态查询方式来访问属性,而是生成一个隐藏的类,当新的属性加入时,改变这个隐藏的类,示例介绍如下:

function Point(x, y) {
  this.x = x;
  this.y = y;
}

当执行new Point(x, y)时,生成一个新的Point对象,当v8第一次执行此动作,会生成一个隐藏的Point类暂叫C0,当执行函数里第一句this.x=x,产生一个新属性x,此时要有个隐藏类C1,取代了C0,这个状态变成C1。接着执行第二句this.y=y,又产生一个新属性y,此时生成新的隐藏类C2代替掉C1,状态变成C2。再有新的属性生成,继续改变隐藏类并代替原来的。这看似是低效的,但如果再new一个Point时,第一次生成的C0,C1,C2..等隐藏类便能重复利用起来,只要不是添加新属性,便不会创建新的隐藏类。这正类似于js里的prototype对象,让所有实例共享一个相同的prototype,节省许多内存开销。v8引擎采用此种方式处理对象属性,并不是原创,但确实用的好。
2、动态机器码
v8第一次执行js时直接编译js为机器码,没有中间代码。v8通过生成隐藏类来优化属性访问,如果某个属性的隐藏类能访问到,则直接执行相应的机器码获取相应属性即可,但碰到新增的属性,没有隐藏类,它会跳转到runtime system(个人觉得是js代码编译时),在已经生成的内部缓存代码上,补充上相应的缺失隐藏类。很显然这样的组合使用,提高了代码执行速度。
3、高校的垃圾回收
为了确保短的垃圾回收暂停,不产生内存碎片等,v8在执行垃圾回收时会停止程序的执行;只回收对象堆的一部分,让停止程序执行的影响减到最小;总是知道对象和指针在内存中的准确位置,这就避免了错误地把对象当做指针而引起的内存泄露。

至此,本文主要内容已经介绍完毕,这么看起来v8设计理念并不复杂,但精巧之处也对于js开发同样有用,js优化方法理论已经很多,部分也与此引擎提出的理论有相似之处,但可以做的似乎更多也需要更彻底。

google介绍v8,自然是希望c++开发者能够使用起来,首先是下载,官方推荐的下载地址:v8,下载后就可以#include <v8.h>...尝试写个hello world了。还有个有关v8引擎的性能测试,这里给出了具体的地址:V8 Benchmark Suite,感兴趣的可以去了解下,具体更复杂应用,请c++开发者另外参考相关文档。

refer


June 18, 2013 | by warmhug | tech