为什么V8 JavaScript引擎这么快
答案:2 悬赏:0 手机版
解决时间 2021-03-06 13:44
- 提问者网友:蓝莓格格巫
- 2021-03-05 20:19
为什么V8 JavaScript引擎这么快
最佳答案
- 五星知识达人网友:低血压的长颈鹿
- 2021-03-05 21:30
因为v8 聘用了java jvm的设计者来制作的v8,会把js先编译在执行,速度大幅提升
全部回答
- 1楼网友:刀戟声无边
- 2021-03-05 23:09
1.针对上下文的snapshot技术
什么是上下文(contexts)?实际是js应用程序的运行环境,避免应用程序的修改相互影响,例如一个页面js修改内置对象方法tostring,不应该影响到另外页面。chrome浏览器每个process只有一个v8引擎实例,浏览器中的每个窗口、iframe都对应一个上下文。
v8启动时(在执行client js前),需要对全局上下文(第一个context)初始化,读取和解析自实现的内置js代码(另一种技术,第2点),建立起function、array、string等内置对象及方法(参见bootstrapper中的genesis类);后续context的创建只需要创建内置对象即可;为了减少全局上下文创建时的cpu、内存消耗,v8使用了snapshot技术(参见v8_mksnapshot工程),(1)全局上下文初始化后,将目前堆内存序列化为字节代码,保存至磁盘文件;这个过程最重要的是空间地址和对象保存,具体操作(参见serialize文件)是:模拟线性内存空间的分配,遍历堆内存中的所有js对象,并在模拟空间分配内存(实际是记录对象相对偏移地址),然后序列化对象大小、偏移地址、子对象、对象内容;最后是序列化global handler和stack上的context;(2)加载时,将该snapshot文件反序列化进内存,避免第一个上下文初始化,从而加快v8的启动。
2. built-in的js代码
利用js自表达内置对象、方法,v8在实现代码转译时只需注重基本操作,以%符号开头的函数来自v8运行时函数(参见runtime和codegen);
3. 建立ast(abstract syntaxtree)时内存的管理
v8在建立ast后,对其进行汇编生成动态机器语言,所以ast在code generated后需要回收;针对ast建立过程中多结点内存申请和一次性回收的特点,v8使用了内存段链表管理,并结合scopelock模式,实现少数申请(segment,8kb~1mb)、多次分配ast结点、一次回收各个segment的管理方式,既能避免内存碎片,又可以避免遍历ast结点逐个回收内存。
4. compilecache避免相同代码重复编译
对于一段js代码,在开始进行词法分析前,会从编译缓存区compilationcache查找该段代码是否已经被编译过,如果是,则直接取出编译过的机器代码,并返回,这样降低cpu的使用率,换来内存空间一定的占用;如果一个页面中重复加载js文件,这方法的提速是很明显的;这种做法应该有平衡对比过。
5. 属性的快速访问
c++、java等语言有着类的概念,且属性、方法和类绑定在一起,访问时可根据对象地址+位移快速获得;而js对象并没有类概念,它实际为hash map,属性可以动态增加、删除,而且在执行时才能获知对象类型。
v8没有像其它js engine使用词典结构或红黑树实现的map来管理属性,而是在每个对象附加一个指针,指向hidden class(如果第一次创建该类型对象,则新建hidden class);当对象每添加一个属性时,将新建一个class(记录了每个属性的位移/位置),而原来的class指向新class,即建立起一个hidden class的转换链表。
6. heap堆内存管理
7. inline caching减少函数调用开销
通过该技术可以记录函数入口,避免重复查找.
8. 一次性编译生成机器语言
一般js engine会在ast生成后,将之编译为中间语言(bytecode),在执行时候再解析这些bytecode;java 也同样编译为这些bytecode,再采用vm(实现跨平台)作为解释器,为了提高效能,java采用混杂方式,把无关平台、常用的代码编译为机器代码。v8则是一次性把ast编译为机器语言。从assembler相关文件头的copyright可以看出,这些不同平台(ia32, arm)下的编译器,原型来自sun microsystems。
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯