2008-04-15
innerHTML的性能问题
关键字: prototype innerhtml replacehtml
看到一遍文章When innerHTML isn’t Fast Enough,反应了innerHTML在操作量大了以后的性能下降的问题。
并且给出了一个replaceHTML的函数
用这个函数来代替innerHTML后在不同浏览器中的性能表现为:
Safari 3:
5000 elements…
innerHTML (destroy only): 63ms
innerHTML (create only): 390ms
innerHTML (destroy & create): 484ms
replaceHtml (destroy only): 47ms (1.3x faster)
replaceHtml (create only): 15ms (26.0x faster)
replaceHtml (destroy & create): 62ms (7.8x faster)
Done.
10000 elements…
innerHTML (destroy only): 110ms
innerHTML (create only): 3500ms
innerHTML (destroy & create): 4735ms
replaceHtml (destroy only): 110ms (~ same speed)
replaceHtml (create only): 31ms (112.9x faster)
replaceHtml (destroy & create): 141ms (33.6x faster)
Done.
Firefox 3:
5000 elements…
innerHTML (destroy only): 863ms
innerHTML (create only): 522ms
innerHTML (destroy & create): 1421ms
replaceHtml (destroy only): 20ms (43.1x faster)
replaceHtml (create only): 225ms (2.3x faster)
replaceHtml (destroy & create): 239ms (5.9x faster)
Done. 10000 elements…
innerHTML (destroy only): 5521ms
innerHTML (create only): 2626ms
innerHTML (destroy & create): 8528ms
replaceHtml (destroy only): 39ms (141.6x faster)
replaceHtml (create only): 373ms (7.0x faster)
replaceHtml (destroy & create): 422ms (20.2x faster)
Done.
Opera 9.5:
5000 elements…
innerHTML (destroy only): 16ms
innerHTML (create only): 141ms
innerHTML (destroy & create): 94ms
replaceHtml (destroy only): 16ms (~ same speed)
replaceHtml (create only): 78ms (1.8x faster)
replaceHtml (destroy & create): 125ms (1.3x slower)
Done.
10000 elements…
innerHTML (destroy only): 31ms
innerHTML (create only): 156ms
innerHTML (destroy & create): 312ms
replaceHtml (destroy only): 31ms (~ same speed)
replaceHtml (create only): 203ms (1.3x slower)
replaceHtml (destroy & create): 157ms (2.0x faster)
Done.
IE7:
1000 elements…
innerHTML (destroy only): 0ms
innerHTML (create only): 0ms
innerHTML (destroy & create): 0ms
replaceHtml (destroy only): 0ms (~ same speed)
replaceHtml (create only): 0ms (~ same speed)
replaceHtml (destroy & create): 0ms (~ same speed)
Done.
15000 elements…
innerHTML (destroy only): 31ms
innerHTML (create only): 156ms
innerHTML (destroy & create): 172ms
replaceHtml (destroy only): 32ms (~ same speed)
replaceHtml (create only): 157ms (~ same speed)
replaceHtml (destroy & create): 188ms (1.1x slower)
Done.
似乎在IE上没有什么改进,但是在其它浏览器上效果明显。
经常使用的prototype.js里是调用Element.update(element,content)来完成innerHTML操作的,打开prototype.js文件,修改update的部分
用replaceHTML函数代替element.innerHTML = content.stripScripts();这行就可以了。
并且给出了一个replaceHTML的函数
function replaceHtml(el, html) {
var oldEl = typeof el === "string" ? document.getElementById(el) : el;
/*@cc_on // Pure innerHTML is slightly faster in IE
oldEl.innerHTML = html;
return oldEl;
@*/
var newEl = oldEl.cloneNode(false);
newEl.innerHTML = html;
oldEl.parentNode.replaceChild(newEl, oldEl);
/* Since we just removed the old element from the DOM, return a reference
to the new element, which can be used to restore variable references. */
return newEl;
};
用这个函数来代替innerHTML后在不同浏览器中的性能表现为:
Safari 3:
5000 elements…
innerHTML (destroy only): 63ms
innerHTML (create only): 390ms
innerHTML (destroy & create): 484ms
replaceHtml (destroy only): 47ms (1.3x faster)
replaceHtml (create only): 15ms (26.0x faster)
replaceHtml (destroy & create): 62ms (7.8x faster)
Done.
10000 elements…
innerHTML (destroy only): 110ms
innerHTML (create only): 3500ms
innerHTML (destroy & create): 4735ms
replaceHtml (destroy only): 110ms (~ same speed)
replaceHtml (create only): 31ms (112.9x faster)
replaceHtml (destroy & create): 141ms (33.6x faster)
Done.
Firefox 3:
5000 elements…
innerHTML (destroy only): 863ms
innerHTML (create only): 522ms
innerHTML (destroy & create): 1421ms
replaceHtml (destroy only): 20ms (43.1x faster)
replaceHtml (create only): 225ms (2.3x faster)
replaceHtml (destroy & create): 239ms (5.9x faster)
Done. 10000 elements…
innerHTML (destroy only): 5521ms
innerHTML (create only): 2626ms
innerHTML (destroy & create): 8528ms
replaceHtml (destroy only): 39ms (141.6x faster)
replaceHtml (create only): 373ms (7.0x faster)
replaceHtml (destroy & create): 422ms (20.2x faster)
Done.
Opera 9.5:
5000 elements…
innerHTML (destroy only): 16ms
innerHTML (create only): 141ms
innerHTML (destroy & create): 94ms
replaceHtml (destroy only): 16ms (~ same speed)
replaceHtml (create only): 78ms (1.8x faster)
replaceHtml (destroy & create): 125ms (1.3x slower)
Done.
10000 elements…
innerHTML (destroy only): 31ms
innerHTML (create only): 156ms
innerHTML (destroy & create): 312ms
replaceHtml (destroy only): 31ms (~ same speed)
replaceHtml (create only): 203ms (1.3x slower)
replaceHtml (destroy & create): 157ms (2.0x faster)
Done.
IE7:
1000 elements…
innerHTML (destroy only): 0ms
innerHTML (create only): 0ms
innerHTML (destroy & create): 0ms
replaceHtml (destroy only): 0ms (~ same speed)
replaceHtml (create only): 0ms (~ same speed)
replaceHtml (destroy & create): 0ms (~ same speed)
Done.
15000 elements…
innerHTML (destroy only): 31ms
innerHTML (create only): 156ms
innerHTML (destroy & create): 172ms
replaceHtml (destroy only): 32ms (~ same speed)
replaceHtml (create only): 157ms (~ same speed)
replaceHtml (destroy & create): 188ms (1.1x slower)
Done.
似乎在IE上没有什么改进,但是在其它浏览器上效果明显。
经常使用的prototype.js里是调用Element.update(element,content)来完成innerHTML操作的,打开prototype.js文件,修改update的部分
update: function(element, content) {
element = $(element);
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) return element.update().insert(content);
content = Object.toHTML(content);
element.innerHTML = content.stripScripts();
content.evalScripts.bind(content).defer();
return element;
},
用replaceHTML函数代替element.innerHTML = content.stripScripts();这行就可以了。
update: function(element, content) {
element = $(element);
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) return element.update().insert(content);
content = Object.toHTML(content);
element = replaceHtml(element, content.stripScripts());
content.evalScripts.bind(content).defer();
return element;
},
评论
lveyo
2008-04-20
hax我看了你的分析文章,我也是用到的时候才发现老外的那篇文章的,也没想去研究为什么会有性能差异,还是你有钻研的精神,以后要多向你学习!
myreligion
2008-04-17
对于返回的 element 使用后是不是需要手动的delete掉? 否则会不会有内存泄露?
fins
2008-04-16
fins
2008-04-16
又分析出一点东西 有时间单独写文章来分析吧
我不能再这样一点一点的回复了 呵呵
我不能再这样一点一点的回复了 呵呵
fins
2008-04-16
又仔细分析一下, 新方法里依然调用了一次innerHTML, 所不同的是这次执行innerHTML的是一个不在dom树中的孤立节点.
那么我们可以理解为 对dom树以外的孤立节点进行innerHTML操作 比对在dom树上的结点更快 (这个还是好理解的)
那么我们可以理解为 对dom树以外的孤立节点进行innerHTML操作 比对在dom树上的结点更快 (这个还是好理解的)
fins
2008-04-16
我看了webkit的代码 一看就明白原因了
但是实在不理解为什么会差这么多:
看看 webkit的里cpp的setInnerHTML方法 :
也就是说 在对el.innerHTML赋值时, 浏览器做的工作实际上就是创建一个临时的节点,然后把这个节点替换 el的所有子结点.
我不明白的是,就这样一个简单的调用关系 为什么在FF下会有那么大的性能差距
有没有哪位朋友来写一下 gecko的实现方法啊
但是实在不理解为什么会差这么多:
看看 webkit的里cpp的setInnerHTML方法 :
void HTMLElement::setInnerHTML(const String& html, ExceptionCode& ec)
{
RefPtr<DocumentFragment> fragment = createContextualFragment(html);
if (!fragment) {
ec = NO_MODIFICATION_ALLOWED_ERR;
return;
}
replaceChildrenWithFragment(this, fragment.release(), ec);
}
也就是说 在对el.innerHTML赋值时, 浏览器做的工作实际上就是创建一个临时的节点,然后把这个节点替换 el的所有子结点.
我不明白的是,就这样一个简单的调用关系 为什么在FF下会有那么大的性能差距
有没有哪位朋友来写一下 gecko的实现方法啊
hax
2008-04-16
我猜测是与innerHTML的实现有关。最好找gecko和webkit的源码看看。
笨笨狗
2008-04-16
太夸张了吧,拷贝个新的dom节点,然后再进行innerHTML操作后替换,这个直觉上让人觉得应该更慢啊,诡异……
fins
2008-04-15
另外发现个问题
这个方法会用新的el替换旧的
在复杂的ajax控件中 那个 el上面往往是有事件的
这种做法会丢失那些事件吧
本来还想用这个方法替换 gt-grid里的部分代码呢
可是突然发现了这个问题 只好作罢了
这个方法会用新的el替换旧的
在复杂的ajax控件中 那个 el上面往往是有事件的
这种做法会丢失那些事件吧
本来还想用这个方法替换 gt-grid里的部分代码呢
可是突然发现了这个问题 只好作罢了
fins
2008-04-15
此文必须要顶
我和hax同惑啊 这个的原理是什么呢?为什么快呢?
以及那个测试是怎么做的呢?
其实测试的方法很重要
t=开始时间
某操作
耗时=现在时间-t
这种算法有时并不能正确的算出"某操作"的时间
我和hax同惑啊 这个的原理是什么呢?为什么快呢?
以及那个测试是怎么做的呢?
其实测试的方法很重要
t=开始时间
某操作
耗时=现在时间-t
这种算法有时并不能正确的算出"某操作"的时间
hax
2008-04-15
great article!
不过我对它的机理还没有想清楚,如果有如此大的性能提升,为什么浏览器自己不做这个优化?
不过我对它的机理还没有想清楚,如果有如此大的性能提升,为什么浏览器自己不做这个优化?
bsspirit
2008-04-15
这个innerHTML, 还真没考虑过性能问题.
我还以为, 除了innerHTML 就是 createElement(), 就这两种方式呢!!
等会,我也试试.
多谢楼主.
我还以为, 除了innerHTML 就是 createElement(), 就这两种方式呢!!
等会,我也试试.
多谢楼主.
发表评论
- 浏览: 7730 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
最近加入圈子
链接
最新评论
-
Spring2结合DWR2的用户注 ...
javaprograms看看是不是你的dwr的包的版本不对呢
-- by lveyo -
Spring2结合DWR2的用户注 ...
哈哈,好啊
-- by kjj -
Spring2结合DWR2的用户注 ...
严重: Context initialization failed org.sp ...
-- by javaprograms -
innerHTML的性能问题
hax我看了你的分析文章,我也是用到的时候才发现老外的那篇文章的,也没想去研究为 ...
-- by lveyo -
innerHTML的性能问题
对于返回的 element 使用后是不是需要手动的delete掉? 否则会不会有 ...
-- by myreligion






评论排行榜