2008-04-16
浅析 innerHTML 性能优化的原理
昨天看了 lveyo老兄的"innerHTML的性能问题" 一文 http://lveyo.javaeye.com/blog/182891
该文介绍了一篇老外的关于提高innerHTML性能的文章.
老外的方法非常的怪异且神奇.
很多朋友在惊叹之余 对于背后的原理非常感兴趣.
受hax的提醒, 我看了一下webkit的代码.在这里我将分析的结果分享出来
说的不一定对 还请大家多多拍砖.
浏览器在 el.innerHTML = newHTML 时所做的工作:
====================================
原始方法
1) 创建一个fragment(document碎片)
2) 将 newHTML 设置到 fragment 内部 (这里怎么设置的不必关心,反正不是用的innerHTML 呵呵)
3) 清除el下的所有子节点 , 类似 el.removeChildren()
4) 将fragment加入到 el内, 类似 el.appendChild(fragment)
====================================
文章里的新方法
1)克隆el节点(不包含子节点),相当于
newEl=document.createElement(el.tagName);
然或将el的所有属性赋值给 newEl (通过 el.getAttribute newEl.setAttribute)
2) 创建一个fragment(document碎片)
3) 将 newHTML 设置到 fragment 内部 (这里怎么设置的不必关心,反正不是用的innerHTML 呵呵)
4) 清除 newEl 下的所有子节点 , 类似 newEl.removeChildren()
5) 将 fragment 加入到 newEl 内, 类似 newEl.appendChild(fragment)
6) 用 fragment 替换 el. 相当于 el.parentNode.replaceChild(newEl, el);
新方法看起来比原始方法更麻烦, 但是为什么速度会更快呢?
关键点就是在 新方法的步骤 4 5 6 .
首先看4:
newEl 是clone的el,但是没有子结点,所以removeChildren很快就返回.相当于没有执行.
而且就算newEL有子结点,由于newEl不是一个在dom树里的节点, 也省去了其中复杂的一步
而 el.removeChildren 这个操作 相比之下自然要耗时很多.原因有三:removeChild操作比较复杂;el有子节点;el和el的子结点都在dom树内.
再来看5
newEl 和 fragment 本身都是脱离dom树独立存在的,这个操作速度也要比el.appendChild(fragment)快.
再来看6.
6的操作就是 在el.parentNode中移除el,然后再在原始位置加入newEl. 这个步骤并没有速度优势.
但是 4 5 6这3个操作加起来,当el和newHTML足够复杂时,还是要比原始方法的 3 4 步更快
以上就是我的分析 有不对的地方 欢迎大家抛砖.
同时欢迎大家来贴一下 IE 和 ff的实现方式
该文介绍了一篇老外的关于提高innerHTML性能的文章.
老外的方法非常的怪异且神奇.
很多朋友在惊叹之余 对于背后的原理非常感兴趣.
受hax的提醒, 我看了一下webkit的代码.在这里我将分析的结果分享出来
说的不一定对 还请大家多多拍砖.
浏览器在 el.innerHTML = newHTML 时所做的工作:
====================================
原始方法
1) 创建一个fragment(document碎片)
2) 将 newHTML 设置到 fragment 内部 (这里怎么设置的不必关心,反正不是用的innerHTML 呵呵)
3) 清除el下的所有子节点 , 类似 el.removeChildren()
4) 将fragment加入到 el内, 类似 el.appendChild(fragment)
====================================
文章里的新方法
1)克隆el节点(不包含子节点),相当于
newEl=document.createElement(el.tagName);
然或将el的所有属性赋值给 newEl (通过 el.getAttribute newEl.setAttribute)
2) 创建一个fragment(document碎片)
3) 将 newHTML 设置到 fragment 内部 (这里怎么设置的不必关心,反正不是用的innerHTML 呵呵)
4) 清除 newEl 下的所有子节点 , 类似 newEl.removeChildren()
5) 将 fragment 加入到 newEl 内, 类似 newEl.appendChild(fragment)
6) 用 fragment 替换 el. 相当于 el.parentNode.replaceChild(newEl, el);
新方法看起来比原始方法更麻烦, 但是为什么速度会更快呢?
关键点就是在 新方法的步骤 4 5 6 .
首先看4:
newEl 是clone的el,但是没有子结点,所以removeChildren很快就返回.相当于没有执行.
而且就算newEL有子结点,由于newEl不是一个在dom树里的节点, 也省去了其中复杂的一步
if (n->inDocument()) n->removedFromDocument();
而 el.removeChildren 这个操作 相比之下自然要耗时很多.原因有三:removeChild操作比较复杂;el有子节点;el和el的子结点都在dom树内.
再来看5
newEl 和 fragment 本身都是脱离dom树独立存在的,这个操作速度也要比el.appendChild(fragment)快.
再来看6.
6的操作就是 在el.parentNode中移除el,然后再在原始位置加入newEl. 这个步骤并没有速度优势.
但是 4 5 6这3个操作加起来,当el和newHTML足够复杂时,还是要比原始方法的 3 4 步更快
以上就是我的分析 有不对的地方 欢迎大家抛砖.
同时欢迎大家来贴一下 IE 和 ff的实现方式
评论
iamjxc
2008-04-22
cloneNode 这种方法的问题是, 原来对象上的事件等会丢失
lveyo
2008-04-20
我也是用到的时候才发现老外的那篇文章的,也没想去研究为什么会有性能差异,还是你有钻研的精神,以后要多向你学习!
fins
2008-04-17
hax 哪里能下载到 gecko 的源代码啊 最好是最新的1.9 nightly的??
fins
2008-04-17
不知道为什么ie处理innerHTML时处理的那么好
还有一个奇怪的问题关于FF的 :
为什么FF在"同步滚动"时 比别的浏览器慢很多 FF2 FF3都是如此
同步滚动:
就是说 你滚动一个overflow:auto的div 时
在 onscroll事件里 同步滚动另一个div
具体效果 可以下载我的 GT-GRID看一下
标题和表头同步滚动效果
FF超级慢
其实没做什么特殊的处理,伪代码如下:
div1.onscroll= { div2.scrollLeft = div1.scrollLeft }
还有一个奇怪的问题关于FF的 :
为什么FF在"同步滚动"时 比别的浏览器慢很多 FF2 FF3都是如此
同步滚动:
就是说 你滚动一个overflow:auto的div 时
在 onscroll事件里 同步滚动另一个div
具体效果 可以下载我的 GT-GRID看一下
标题和表头同步滚动效果
FF超级慢
其实没做什么特殊的处理,伪代码如下:
div1.onscroll= { div2.scrollLeft = div1.scrollLeft }
hax
2008-04-17
我看了一下gecko的实现。它是先取得一个range,然后range->deleteContents,然后range->createContextualFragment。
而克隆替换法(暂且叫这个名吧)中,估计不需要deleteContents,而且createFragment时没有ownerDocument貌似也会少许多步骤。
而克隆替换法(暂且叫这个名吧)中,估计不需要deleteContents,而且createFragment时没有ownerDocument貌似也会少许多步骤。
fins
2008-04-16
利用 不在dom树中的节点 来加速 确实和双缓冲比较像啊 哈哈
看来你是弄 android弄入魔了
看来你是弄 android弄入魔了
差沙
2008-04-16
哦,确实有道理呀,看起来有点像是UI显示里面的双缓冲似的。
发表评论
- 浏览: 743365 次
- 性别:

- 来自: 小胖儿的大城

- 详细资料
搜索本博客
我的相册
customHead
共 76 张
共 76 张
链接
最新评论
-
再发一篇牢骚贴: 文档又丢 ...
文档也是要入CVS的。
-- by bottom -
GT-Grid开发笔记: 这几天 ...
惊鸿逝水 写道>>关于价值,如果GT收费,那么它值多少钱呢? 10元吧 10 ...
-- by lonelyblue -
蝙蝠侠6票房过$2亿之后的 ...
强烈鄙视 剧透的人 尤其是 剧透之前 不写明"剧透 慎入"的人 这电影在我心里 ...
-- by fins -
蝙蝠侠6票房过$2亿之后的 ...
看了。。感想: --BATMAN如果不是有超强的装备,一定是JOKER笑到最后。 ...
-- by dimvar -
GT-Grid "缺陷,、bug、 ...
问题不是出在这 你等着新版本吧 一个属性搞定 :) 今天晚上发布 (前提是 ...
-- by fins






评论排行榜