Web 技术研究所

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

再探DOM操作带来的额外性能问题

  上一篇文章中只是从添加元素的问题上涉入了这个问题,但我觉得这个问题是个重点。我们一直以来备受DOM操作低效率的困扰,直接把所有责任都推给DOM是不对的。在DOM背后还有一个和它一样糟糕的家伙在坑效率。这家伙有时候会带来比DOM本身更严重的问题。
  DOM的操作本身是同步的,代码执行完的同时操作也完成了,但这“完成”仅限于DOM本身。DOM操作完成只是在当前脚本运行所在的消息中,我们在这里干的坏事不会立即遭报。当这个消息结束时候,CSS重新计算我们对文档影响的部分,如果这部分很大就需要大量的时间。我们可以做这样的测试 <script>
document.onclick=function(){
  var i,t,div,body;
  t=new Date;
  body=document.body;
  for(i=0;i<1E4;i++){
    div=document.createElement("div");
    body.appendChild(div);
  };
  console.log(new Date-t+" <- DOM操作耗时");
  t=new Date;
  setTimeout(function(){
    console.log(new Date-t+" <- CSS渲染耗时");
  });
};
</script>

  这个代码只测试了1E4个元素,可把我们的Chrome累坏了,Firefox和IE躲在一旁笑嘻嘻。Chrome的问题应该是出在它渲染引擎的某些算法上。我做了很多测试,Chrome的渲染引擎在添加元素的问题上是指数时间复杂度,而Firefox和IE则是线性时间复杂度。所以元素的数量一多Chrome就吃不消了。但这篇文章要说的关键不是Chrome渲染引擎的BUG,而是渲染本身带来的性能开销。我们看Chrome中对上面代码工作的耗时分布

  RecalculateStyle的耗时是很大的,这个测试还是在完全没有用户CSS的环境下测试的,如果我引入一个非常复杂的CSS,那么这个计算时间还得增加许多。当然这个图是Chrome上的,RecalculateStyle的耗时比较夸张。但是即使在Firefox和IE上,他们至少也是线性的时间复杂度。
  很多文章中说使用文档片段(DocumentFragment)来优化DOM操作的性能,这种说法是建立在“DOM操作实时计算CSS”的设想上的。如果DOM操作实时计算CSS,那确实可以合并这些计算起到优化作用。但实际上计算CSS的步骤并不在操作DOM时进行,而是在单独的消息中完成的,所以文档片段在这方面不能带来优化。
  操作DOM和计算CSS,这两个步骤都是必不可少的。线性的时间复杂度已经是最优的了。如果说可以优化,我们只能针对Chrome的这个BUG来优化,解决在Chrome上的问题。如果非要对这整个问题进行优化就得从问题的根本入手,避免大规模的文档结构变化。
  最后我只想说,让文档变得如此巨大的程序本身就不是好程序!
网名:
54.226.58.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^