“现代”浏览器可以同时“处理”多少个HTML元素?

时间:2014-02-06 19:09:25

标签: html json performance dom

“modern”因为该定义可能会随着时间的推移而改变(具体而言我指的是桌面浏览器)

“句柄”,因为它可能因机器配置/内存而异,但具体而言我指的是一般用例。


我想解决一个涉及大型数据集的特定问题。

基本上,每当对特定数据集进行更改时,我都会返回完整数据集,并且必须在浏览器中呈现此数据。

例如,在websocket上我得到一个推送事件,告诉我数据集已经发生了变化,然后我必须通过抓取现有的DOM元素,复制它,用这里的数据填充元素来在HTML中呈现这个数据集。使用类名或其他元素标识符设置,然后将其添加回DOM。

请记住,此数据集中的任何对象(JSON)可能包含多达1000个以上的子对象,并且可能有多达10,000个以上的父对象,因此您可以看到可能存在返回的实例数据集向上朝向1,000,000 => 10,000,000个数据点或更多。

现在有趣的部分来了,我必须渲染这些东西。对于每个数据点,可能有3或4个标记用于呈现和样式化数据,并且可能有任何这些标记的事件侦听器(可能在父容器上使用委托来减轻事情)。

总结一下,可能会有很多需要呈现的传入信息,而我正试图找出处理这种情况的最佳方法。

理想情况下,您只想渲染具有更改而不是重新渲染整个集合的单个数据点的更改,但由于后端的设计方式,这可能不是一个选项。

我主要关心的是了解浏览器/ DOM的局限性,并通过前端镜头查看此问题。在后端肯定会发生一些变化(数据设计,缓存,分页),但这不是重点。

这不是HTML / DOM的典型用例,因为我知道存在局限性,但究竟是什么?我们仍然限制在大约3000-4000个元素吗?


我为related subquestions actively提供了looking up,但我觉得这很好与stackoverflow社区的其他成员分享一些想法,并尝试将有关此问题的一些信息汇总在一起。

现代浏览器在开始变慢/无响应之前可以处理的“合理”数量的DOM元素是什么?

如何对浏览器可以处理的DOM元素数进行基准测试?

有哪些strategies用于处理需要渲染的大型数据集(除了分页)?

与使用jQuery或正则表达式相比,使用数据/ json(在前端)渲染html等模板框架(如胡子和把手)的性能是否更高?

4 个答案:

答案 0 :(得分:7)

你的回答是:1或数百万。我打算在SO上复制/粘贴类似问题的答案。

  

说实话,如果你真的需要这个问题的绝对答案,那么你可能想重新考虑你的设计。

     

这里没有给出答案是正确的,因为它取决于您的申请特定的许多因素。例如。沉重与小   CSS使用,div的大小,实际图形渲染的数量   每个div需要,目标浏览器/平台,DOM事件的数量   听众等。

     

仅仅因为你并不意味着你应该这样做! :-)“

请参阅:how many div's can you have before the dom slows and becomes unstable?

这确实是一个无法回答的问题,在太多角度有太多因素。我会说这个,然而,在单页加载中,我使用了1ms的javascript setinterval来不断地将新的div添加到ID递增1的页面。我的Chrome浏览器刚刚超过20,000,并且使用600MB Ram。

答案 1 :(得分:3)

这个问题只有一个统计上精明的答案才能准确和全面。

<强>为什么

适当的等式是这样的,其中N是节点数,字节 N 是在DOM中表示它们所需的总字节数,节点索引范围是n ∈ [0, N),bytesOverhead是用于具有绝对最小属性配置且没有innerHTML的节点的内存量,bytesContent是用于填充此类最小节点的内存量。

  

bytes N N (bytesContent n + bytesOverhead n

问题中请求的值是最差情况下手持设备,操作系统,浏览器和操作条件下的N的最大值。为每个排列求解N并非易事。上面的等式揭示了三个依赖关系,每个依赖关系都可以彻底改变答案。

<强>依赖关系

  1. 节点的平均大小取决于每个节点用于保存内容的平均字节数,例如UTF-8文本,属性名称和值或缓存信息。
  2. DOM对象的平均开销取决于管理每个文档的DOM表示的HTTP用户代理。 W3C的Document Object Model FAQ州,&#34;虽然所有DOM实施都应该可以互操作,但它们在代码大小,内存需求和各个操作的性能方面可能会有很大差异。&# 34;
  3. 可用于DOM表示的内存取决于默认使用的浏览器(可能因手持设备供应商或用户更喜欢的浏览器而异),默认浏览器的用户覆盖,操作系统版本,内存容量手持设备,常见后台任务和其他内存消耗。
  4. 严谨的解决方案

    可以运行测试来确定手持设备上使用的每个常见http用户代理的(1)和(2)。任何给定站点的用户代理的分布都可以通过配置Web服务器的日志记录机制来放置HTTP_USER_AGENT(如果默认情况下不存在),然后剥离除日志中的所有字段并计算实例每个值。

    每个字符的字节数都需要针对属性值和UTF-8内部文本(或任何编码)进行测试,以获得一组明确的计算因子(1)。

    在各种常见条件下,可用的存储器也需要进行测试,这本身就是一项重大的研究项目。

    所选N的特定值必须为ZERO才能处理实际的最坏情况,因此可以选择一定百分比的典型内容,节点结构和运行时条件。例如,可以使用某种形式的随机原位(在正常环境条件下)研究中获取病例样本,并找到满足95%这些病例的N.

    也许可以通过上述方式测试一组案例,并将结果放在表格中。这样就可以直接回答你的问题。

    我猜这将需要一位受过良好教育的移动软件工程师,因为数学,特别是统计数据,需要五个整周时间来获得合理的结果。

    更实际的估算

    可以猜出最糟糕的情况。通过几天的研究和一些概念验证应用程序,这个提案可以改进。没有时间这样做,这是一个很好的初步猜测。

    考虑一个允许1 GB用于DOM的手机,因为正常的操作条件使用4 GB中的3 GB用于上述目的。可以假设节点的平均内存消耗如下,以得到一个大概的数字。

    • 每个字符2个字节,每个节点有40个字符的内部文本
    • 每个字符2个字节,每个字符值为10个字符的
    • 每个字符1个字节,每个字符4个字符的4个属性名称
    • 160个字节用于效率较低的情况下的C / C ++节点开销

    在这种情况下,N worst_case ,最差情况下的最大节点,

    = 1,024 X 1,024 X 1,024
      / (2 X 40  +  2 X 4 X 10  +  1 X 4 X 4  +  160)
    
    = 3,195,660 . 190,476.
    
    但是,如果可以完全避免,我不会在具有三百万个DOM节点的浏览器中构建文档。考虑采用下面更常见的做法。

    常规练习

    最好的解决方案是远远低于N worst_case ,并且只需使用标准HTTP设计技术将节点总数减少到可能的程度。

    • 减少任何给定页面上显示的内容的大小和复杂性,这也提高了视觉和概念的清晰度。
    • 从服务器请求最少量的数据,使用窗口技​​术推迟尚未显示的内容,或者以精心策划的方式平衡响应时间和内存消耗。
    • 使用异步调用来协助上述极简主义。

答案 2 :(得分:2)

对于那些想知道的人:Google有 Dom size建议

Domsize recommandations


最佳DOM树:

  • 总共少于1500个节点。
  • 最大深度为32个节点。
  • 没有父节点且子节点超过60个。

通常,寻找仅在需要时创建DOM节点并在不再需要时销毁它们的方法。

如果您的服务器附带了一个大型DOM树,请尝试加载页面并手动注意显示的节点。也许您可以从加载的文档中删除未显示的节点,然后仅在用户手势(例如滚动或单击按钮)之后创建它们。

如果在运行时创建DOM节点,则子树修改DOM更改断点可以帮助您查明何时创建节点。

如果您无法避免大型DOM树,则另一种提高渲染性能的方法是简化CSS选择器。请参见减少样式计算的范围和复杂性。

答案 3 :(得分:1)

DOM 元素过多的方式有多种。这是一个 React + d3 组件,我一直在使用它来渲染许多元素并更真实地了解 DOM 的限制:

export const App = React.memo((props) => {
  const gridRef = React.useRef(null);
  React.useEffect(() => {
    if (gridRef.current) {
      const table = select(gridRef.current);
      table
        .selectAll("div")
        .data([...new Array(10000)])
        .enter()
        .append("div")
        .text(() => "testing");
    }
    if (props.onElementRendered) {
      props.onElementRendered();
    }
  }, []);
  return <div ref={gridRef} />;
});

在配备 16GB 内存并运行 Chrome 的 2021 年 Macbook Pro 上,我看到从大约 30,000 个元素开始出现严重延迟(我认为是在绘制步骤)