v8引擎的优化

1、编译优化

V8采用JIT即使编译技术.

例如JAVA是先编译成字节码,再由JVM编译成机器码,V8则没有中间的字节码,直接由源码生成语法树,然后编译成机器码.

 

2、隐藏类

当定义一个构造函数,使用这个函数生成的第一个对象的时候,v8会为它初始化一个隐藏类,以后使用这个构造函数生成的对象指向同一个隐藏类.当对这个构造函数新增或者删除属性或者方法时,会派生出新对隐藏类.隐藏类起到了给对象分组对作用,同一组对象,具有相同的成员名称,隐藏类记录了成员的名称和偏移量,根据这些信息,V8能够按照对象首地址+偏移量访问成员变量,程序中,相对于把属性名作为键值,使用字典的查找方式存取成员,使用索引方式性能的改进更明显.

 

3、内联缓存

成员的索引是以哈希表的方式存在隐藏类中,如果每次存取属性都搜寻隐藏类的哈希表,这种使用偏移量的方式不会带来任何好处.

内敛缓存是基于程序运行的局部性原理,动态生成使用索引查找的代码,下次存取成员就不必再去搜寻哈希表了.

 

4、优化回退

当V8发现某函数执行频繁,就将其标记为热点函数,认为此函数比较稳定,类型已经确定,于是调用Crankshaft编译器,生成更高效的机器码,后面万一遇到类型变化,V8采取将JS函数回退到优化前的较一般情况.

回退过程就是根据函数源码,生成响应语法树,然后编译成一般形式的机器码,可以预见这个过程比较耗时,要避免这种情况.

//bad case
function add(a,b){ return a + b } for(let i = 0; i < 5; i++) { add(i, i+1) } add('a', 'b')

// good case
function add(a,b){
  return a + b  
}
function addStr(a,b){
  return a + b  
}
for(let i = 0; i < 5; i++) { 
  add(i, i+1)
}
addStr('a', 'b')

  函数内部参数类型越确定.V8越能够生成优化后代码.

posted @ 2019-11-26 11:24  地铁程序员  阅读(504)  评论(1编辑  收藏  举报