渲染优化和兄弟选择器

can*_*era 14 css performance webkit internals

WebKit浏览器具有内置的样式渲染优化技术,"甚至不必匹配页面上大约60%元素的样式."

但是,如果"在样式表中的任何地方遇到任何兄弟选择器......那么优化将完全关闭整个页面...这包括+选择器和选择器,如:first-child:last-child."

有谁知道禁用此优化的选择器类型的完整列表?

-

更多信息

  • Tali Garsiel关于浏览器内部的研究讨论了优化:浏览器如何工作.

  • 以下是来自Dave Hyatt的兄弟选择器的完整报价,他显然是在编写浏览器代码:"必须没有使用兄弟选择器.当遇到任何兄弟选择器时,WebCore会抛出一个全局开关,并禁用整个文档的样式共享当它们存在时.这包括+选择器和选择器,如:first-child和:last-child."

  • 这句话似乎来自于2005年凯悦写的一篇文章.下面他将更详细地讨论它(与之前相同的来源):

    "WebCore(在即将推出的Safari版本中)有一个非常酷的优化,我提出来避免甚至不得不计算应用于元素的声明集.这种优化在实践中甚至不必匹配页面上大约60%元素的样式.优化背后的想法是识别页面中的两个元素何时出现通过DOM(和其他状态)检查获得相同的样式,并尽可能简单地在这两个元素之间共享前端样式信息."

  • Nate Koechley的这篇文章更详细地讨论了算法.他总结道:

    "在网络开发中,通常有6种不同的相似方式来做同样的事情.一个优秀的网络开发人员不断选择最好的几乎无法区分的路径.这些来自凯悦的内部提示让我们更完整了解浏览器的内容,并帮助我们选择最佳方法."

  • Hyatt还讨论了此W3C邮件列表存档中的优化问题

  • 在Ryan Kinal 的Stack聊天中也简要介绍了一下:"哇.哇哇.我永远不会再使用另一个兄弟选择器了."

我特别感兴趣的是:

  • 子选择器是否也关闭优化

  • Trident/IE是否使用任何类似的优化

  • 是否存在任何测试表明它对渲染性能有多大差异

dan*_*l__ 2

我没有完整的列表,但我认为来自 mozilla 和 Servo 的这段文字可能会有所帮助。

WebKit 对样式更新的处理

属性变化

如果该元素尚未标记样式重新计算,并且该属性是 id 属性或者存在涉及该属性的选择器,则该元素将被标记为样式重新计算。在此阶段,不会尝试仔细检查这些选择器是否与该元素有关,也不会尝试处理涉及“ ~”和“ +”的情况。当类属性更改时,还会调用一个单独的钩子,该钩子除其他外无条件地将元素标记为需要样式重新计算。同样,不会尝试处理“ ~”和“ +”。在这些情况下,都没有尝试优化后代的选择器匹配。

状态变化

WebKit 中没有统一的状态更改设置。对于 Gecko 中通过布尔状态处理的每个伪类,选择器匹配都有一个专用函数,它可以调用该元素来测试该伪类是否匹配。元素内部状态的更改负责直接将该元素标记为需要样式重新计算。同样,没有尝试优化后代上的选择器匹配或处理“ + ”或“ ~”。这里有一些类似于 Gecko 为该:hover封面所做的优化:hover:active,以及一些关于拖动的优化。

插入和删除的处理

RenderStyle 具有指示其子级是否受到各种结构伪类和“ +”或“ ~”组合器影响的标志。在 DOM 突变中,更改后第一个受影响的元素(按子列表顺序)被标记为需要样式重新计算,或者父级的单个第一个子元素(如果可能需要重新计算)。如果更改之前的更多内容可能需要重新计算,则父级将被标记为需要样式重新计算,这将重新计算其所有子级。在所有这些情况下,当实际重新计算元素上的样式时,会检查其子元素是否受到 ' +' 或 ' ~' 的影响。如果是这样,那么如果任何子项被标记为需要样式重新计算,那么它之后的子项或它之后的所有子项(取决于是否涉及“ +”或“ ”)也被标记为需要样式重新计算。~我认为,围绕多个“ +”链存在一些错误。

结果是,据我所知,在某些情况下,WebKit 最终会在比 Gecko 更多的元素上重新计算样式,但在其他情况下,它最终会在更少的元素上重新计算样式。例如,给定一个像“ .foo ~ span”这样的选择器和一个将类从“foo”更改为“bar”的 div,Gecko 将重新设置该 div 的所有后续同级元素的样式,而如果没有“span”,WebKit 将根本不会执行任何工作孩子们,因为在这种情况下它永远不会将父母标记为受到“ + ”的影响。我不确定这会在多大程度上影响插入行为,看起来两者应该更相似。不知何故,WebKit 在 HTML5 单页规范脚本上似乎比 Gecko 做得更好,但我目前不明白为什么。也许这只是因为它的样式重新计算似乎比 Gecko 的实际运行成本要低得多。

另一个结果是,个体属性和状态更改所涉及的工作比 Gecko 少得多,但代价是需要更多的样式重新计算。DOM 插入/删除涉及的工作大致相同。

来源