Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

关于v8的内联缓存和隐藏类

  在往对象上添加属性时,v8就会生成隐藏类,这些隐藏类是用于内联缓存的。同类对象的属性可以直接从内联缓存上访问,不需要每次都去查找。隐藏类又基于[[Prototype]]内置属性来分类,不同[[Prototype]]的对象之间的隐藏类是各自独立的。
  v8的内联缓存(Inline Cache)和C++中的inline优化是完全不同的概念。虽然都名为“inline”,但C++的inline优化是针对函数调用的堆栈访问优化,而v8的内联缓存是针对具有相同属性的JavaScript对象的通用属性访问优化。
  我们做这样一个测试 <input type="button" value="test" id="test" />
<script>
test.onclick=function(){
  var i,t=new Date,o;
  for(i=0;i<1E4;i++)o={},o["n"+i]=i;
  console.log(new Date-t);
};
</script>

  这个代码在Chrome上怎么那么慢!?这就是因为v8在为每一个拥有不同属性的Object实例维护着一份隐藏类(Hidden Class)。随着同一个基类([[Prototype]]内置属性相同的对象称为同一个基类的对象)上的隐藏类的增加,维护成本是呈代数级增长的(时间复杂度O(na))。所以在这个测试中,Chrome比Firefox和IE慢的多。但在上面的测试中多点几次test按钮就会发现之后的速度是很快的,因为在第一次执行时所有用到的隐藏类就已经生成完毕。但需要注意的是内联缓存的数据可以被GC回收,所以即使上面的测试在第一次以后速度很快,一旦过了GC回收的时间就需要重新生成这些隐藏类,结果又会变得很。
  内联缓存当然有它的优点,上面的测试是比较极端的,这是为了演示内联缓存的软肋。对于大量具有相同属性对象的情况,内联缓存就非常有优势,而且这种情况是普遍存在。比如下面这个测试Chrome就比Firefox快。 <input type="button" value="test" id="test" />
<script>
test.onclick=function(){
  var i,t1=new Date,t2,o={
    a:0,b:0,c:0,d:0,e:0,f:0,g:0,h:0,i:0,
    j:0,k:0,l:0,m:0,n:0,o:0,p:0,q:0,r:0,
    s:0,t:0,u:0,v:0,w:0,x:0,y:0,z:0
  };
  for(i=0;i<1E7;i++)
    o.a=o.b=o.c=o.d=o.e=o.f=o.g=o.h=o.i=
    o.j=o.k=o.l=o.m=o.n=o.o=o.p=o.q=o.r=
    o.s=o.t=o.u=o.v=o.w=o.x=o.y=o.z=i;
  t1=(t2=new Date)-t1;
  for(i=0;i<1E7;i++);
  t2=new Date-t2;
  console.log(t1-t2); //减去循环本身的性能损耗
};
</script>

  这个例子上是访问普通对象的普通属性,正常这些属性是被hash存储的。但在内联缓存优化中它被创建了隐藏类,所以属性访问不需要经过hash查找就可以直接得到地址。IE可能也使用了类似的优化方式,它的速度并不慢。
  当然,内联缓存这东西有时候反而拖慢性能,就比如这篇文章中的第一个测试。对于这种情况,我们可以不把所有内联缓存全都直接丢在Object实例上。只要对象的[[Prototype]]内部属性不同就不会产生隐藏类堆积的情况,我们只要让对象的[[Prototype]]不同即可。下面这个代码就是第一个测试的优化方案,直接让每个对象的[[Prototype]]内部属性都不同即可。当然,这只在v8上具有优化作用,对其它引擎可能带来反效果。 <input type="button" value="test" id="test" />
<script>
test.onclick=function(){
  var i,t=new Date,o;
  for(i=0;i<1E4;i++)o=Object.create({}),o["n"+i]=i;
  console.log(new Date-t);
};
</script>
  以上这些就是v8内联缓存的基本概念,其实我了解的也不深,以后有什么体会继续补充。
网名:
54.144.24.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^