通过 innerHTML 对 DOM 操作进行性能测试

Posted

技术标签:

【中文标题】通过 innerHTML 对 DOM 操作进行性能测试【英文标题】:performance test of DOM operations via innerHTML 【发布时间】:2011-03-08 07:00:26 【问题描述】:

根据 *** 的精神(感谢@Bill the Lizard 澄清这一点),我想介绍一下所有前端 Web 开发人员都知道的小问题。

如何在编写 Dhtml、使用 innerHTML 或 DOM 操作时获得更好的 jscript 性能?

为了测试,我创建了带有“开始测试”按钮的单个 HTML 页面,该按钮运行 5000 次功能对,该功能是使用 innerHTML 思想或由 DOM 编写的。 (可上:http://codepad.org/HyiKRsNk)

为了避免比较 CPU 结果以百分比显示,一个函数如何比另一个更快。因此,如果您看到 (17%),则意味着 DOM 更快 innerHTML,如果(可能是后者)您看到 (-5%),则意味着 innerHTML 比 DOM 更快。 为避免内存爆炸的影响,每次调用都会在测试后立即创建和删除新的“测试区域”(没有遇到创建/删除时间)。 测试在 display:none div 下进行以避免翻转和滚动时性能下降

我准备了3个测试(@tomdemuyt提出的最后一个)

    为其创建新的 DIV 和子文本

    删除部分DIV(为避免创建差异的影响,两个测试使用相同的方式创建测试div,但删除不同)

    添加 onclick 事件处理程序

    深度测试树的创建,测试创建<table><tbody><tr><td><span>text 构造。 DOM 测试使用对 createElement/appendChild 的顺序调用

    与 (4) 类似,但创建了 2 行 <tr>。 DOM 使用特殊的辅助函数来简化:

    treeHelper("table", 
        treeHelper("tbody", 
            treeHelper("tr", 
    

不同浏览器的测试结果如下。

所以亲爱的同事请提供:当 innerHTML 更快时显示一些测试,在尚未列出的浏览器上开始我的测试。

【问题讨论】:

有很多变化会影响性能。 1.)哪个浏览器,2.)您要插入哪些元素,3.)要插入的元素/DOMString 的数量等。特别是旧版本的 IE 存在主要的字符串连接性能问题,因此即使 .innerHTML 插入可能更快与构建 DOM 相比,由于字符串 concat 问题,IE 会更慢。 @scunliffe - 根本没有连接!仅附有完整的字符串,请在下面查看我的答案,以下是 4 个浏览器的列表。如果您能提供更多 - 那就太好了! true 在这个测试中它可能只是一个简单的字符串,但实际上你将构建各种元素集合(例如,整个表格,包装在一个表单中,在一个 div 中放入页面的某个地方)。您还需要注意,您无法在 IE 中设置某些 .innerHTML 值,反之亦然,在 IE 中的标准 DOM 操作中您无法执行许多操作。像 jQuery 这样的 JS 库在这里真的很有帮助,因为它们可以将你从这些浏览器的差异中分离出来。 @scunliffe 抱歉,例如,无法理解,“...实际上您将构建各种元素集合...”这如何影响基准测试什么是更快的 DOM 或 innerHTML?您能否提供描述您想法的测试用例或场景,我会将其放入所有测试集合中。 【参考方案1】:

基于原始问题的 cmets,我在此处添加了一个答案,详细说明了为什么直接向上 .innerHTMLDOM manipulation 比较很难简明地评估。

基本上有几个主要问题:

    浏览器错误和缺少实现 内容差异(在 A 情况下效果更好,在 B 情况下可能不会更好) 时间问题(javascript 无法控制或洞察浏览器何时决定执行 GC(垃圾收集)或运行其他线程/活动

1.) 特别是 IE(6,7 和较小程度的 8)有一堆浏览器错误,导致对所有代码场景进行全面测试。 (IE 有错误,无法在 selecttabletheadtbodytfoottr 上设置 .innerHTML,内容所在的空元素设置为 auto高度超过 1 个“行”,pre 内容包含重要空白的元素等)

2.) 添加的子节点的数量、类型(顺序)和深度将改变操作的性能。例如。通过添加 table 标签来添加表格,然后是 tbody,然后是 tr,然后是 td,然后是 content,而不是单独构建它并将其转储到页面中会改变性能。

3.) 浏览器控制它何时执行 GC(这会在浏览器进行清理时减慢浏览器的速度)。同样,浏览器扩展程序或另一个选项卡中的 AJAX 调用,IE8 中的 Web 切片会轮询服务器以获取将影响当前页面执行方式的更新。

因此,如果您想对此进行全面测试,则需要测试几种不同的 HTML 子结构组合,我非常希望结果会有所不同。

我在家里有一些针对这类事情的旧测试,我会挖掘并添加到这个答案中以进行更多涉及的测试。

【讨论】:

根据您的建议,刚刚添加了 +2 测试以深入了解树的性能【参考方案2】:

歌剧(10.54):

Test                                Result 
1.insert new element and text         30.00%
2.removeChild vs innerHTML=''         66.67%
3.set event handler                   245.45%
4.test in depth of tree linear        -62.16%
5.test in depth of tree (using helpr) -67.10%

Chrome (5.0.375.70):

Test                                 Result
1.insert new element and text          318.18%
2.removeChild vs innerHTML=''          53.85%
3.set event handler                    150.00%
4.test in depth of tree linear         41.67%
5.test in depth of tree (using helpr) -33.03%

火狐(3.6.4):

Test                                  Result
1.insert new element and text           76.17%
2.removeChild vs innerHTML=''           50.56%
3.set event handler                     1097.44%
4.test in depth of tree linear          32.94%
5.test in depth of tree (using helpr)   9.66%

IE(8):

Test                                  Result 
1.insert new element and text           46.92%
2.removeChild vs innerHTML=''           26.34%
3.set event handler                     936.17%
4.test in depth of tree linear          -35.42%
5.test in depth of tree (using helpr)   -67.26%

已编辑(1): 为每个浏览器添加 2 行深度构建树测试(树线性深度测试,树深度测试(使用帮助器))。发现大多数浏览器不喜欢堆栈分配值,因为线性 appendChild, appendChild... 比在 treeHelper('table', treeHelper('tbody', ....

【讨论】:

以上是关于通过 innerHTML 对 DOM 操作进行性能测试的主要内容,如果未能解决你的问题,请参考以下文章

jQuery-性能优化-避免不必要的 DOM 操作

JavaScript Dom 操作

DOM API 或 innerHTML 哪个更适合 DOM 操作?

07-DOM操作练习:innerHTML的方式创建元素

DOM的基本操作

JavaScript--更新DOM