我们一直以来备受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上的问题。如果非要对这整个问题进行优化就得从问题的根本入手,避免大规模的文档结构变化。
最后我只想说,让文档变得如此巨大的程序本身就不是好程序!
日期:2015年04月21日
标签: 广州网站设计公司 、 广州网站设计 、 广州网站建设公司 、 广州网站建设 、 广州网站制作公司 、 广州网站制作 、 高端网站设计 、 高端网站建设 、 广州高端网站设计 、 广州高端网站建设