【问题标题】:Recalculate Style: why so stuttering?重新计算风格:为什么这么口吃?
【发布时间】:2013-11-16 17:51:39
【问题描述】:

假设我们有一个将一系列相似元素注入 DOM 的代码。像这样的:

var COUNT = 10000,
    elements = Object.keys(Array(COUNT).join('|').split('|'));

var d = document, 
    root = d.getElementById('root');

function inject() {
    var count = COUNT,
        ul     = d.createElement('ul'),
        liTmpl = d.createElement('li'),
        liEl   = null;

    console.time('Processing elements');
    while (count--) {
        liEl = liTmpl.cloneNode(false);
        liEl.textContent = elements[count];
        ul.appendChild(liEl);
    }
    console.timeEnd('Processing elements');

    console.time('Appending into DOM');
    root.appendChild(ul);
    console.timeEnd('Appending into DOM');
};
d.getElementById('inject').addEventListener('click', inject);

Demo.

当这个 sn-p 在 Firefox (25.0) 中运行时,调用 'inject' 和实际看到它的结果之间的时间与time/timeEnd 记录的时间相对应。对于 1000 个元素,大约 4 ms; 10000,大约 40 等等。很正常,不是吗?

但是,对于 Chrome(30.0 和 Canary 32.0 已测试),情况并非如此。虽然报告的处理和附加时间实际上少于 Firefox,但渲染这些元素需要更多时间。

困惑的是,我检查了 Chrome 的分析器以了解不同的场景 - 结果发现瓶颈在于重新计算样式操作。 10000个节点需要2-3秒,20000个节点需要8秒,30000个节点需要17秒。


现在真正的问题是:有没有人遇到过同样的情况,有什么解决方法吗?

我们考虑过的一种可能的方法是将这些节点的可见性限制在一种延迟加载中(“一种”,因为它更多的是“延迟显示”:元素已经就位,只有它们的能见度将受到限制)。确认“重新计算样式”仅在元素即将变得可见时触发(实际上这是有道理的)。

【问题讨论】:

  • Chrome 曾经是最好的浏览器。如今,没有那么多。其他浏览器已经赶上了 Chrome,而 Google 显然已经将重点放在了适用于手持设备的 Chrome 上。
  • 旁注,因为您似乎喜欢技巧:我会使用较短的 Object.keys(Array.apply(0,Array(COUNT))) 而不是 Object.keys(Array(COUNT).join(',').split(','))
  • 好吧,我想我应该把它作为评论而不是答案,因为它是推测性的:我认为许多浏览器已经优化了“appendChild”,以便将少量节点添加到单个元素。但是,您可能想尝试使用“innerHTML”进行相同的测试——这更有可能在 C++ 代码中进行了优化,以便一次添加大量 HTML;就像当你加载一个巨大的页面时会发生什么。使用 javascript 附加所有内容时,您正在尝试自己处理浏览器的工作。 (不过,对于小的添加/更改,innerHTML 确实是矫枉过正)
  • @Katana314 I tested.

标签: javascript css performance google-chrome


【解决方案1】:

看起来问题在于具有display:list-itemli 元素

如果您使用 div 元素而不是 ul/li 元素,它在 chrome 中的运行速度非常快..

同时创建 li{display:block;} 的 css 规则修复了延迟。

手动添加 list-item 会显示延迟,即使元素已经在 DOM 中渲染(它们当然必须重新渲染

http://jsfiddle.net/6D7sM/1/查看演示

(所以看起来 chrome 在渲染display:list-item 元素方面很慢)


还有一个相关的错误提交给 chrome http://code.google.com/p/chromium/issues/detail?id=71305,它已被合并到 http://code.google.com/p/chromium/issues/detail?id=%2094248 中(看起来在早期版本中它会导致 chrome 崩溃,但它已被修复。崩溃,而不是速度 )

【讨论】:

  • 这非常有帮助,谢谢!我想我应该为此提交一个错误报告 - 至少我看不出为什么应该以不同的方式处理 list-item 元素的合理解释。
  • @raina77ow 它们确实与其余元素有一些内在差异,例如我假设通过 CSS 计数器进行的项目符号/数字装饰(ol 元素的编号) ,但禁用这些没有任何区别,所以问题出在其他地方..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多