Home  >  Article  >  Web Front-end  >  [Human brain supplement computer translation] CSS Selector Performance has changed! (For the better) by Nicole Sullivan_html/css_WEB-ITnose

[Human brain supplement computer translation] CSS Selector Performance has changed! (For the better) by Nicole Sullivan_html/css_WEB-ITnose

WBOY
WBOYOriginal
2016-06-24 11:47:371129browse

CSS选择器的执行效率已经改变了(增强)

像Dave Hyatt的Writing Efficient CSS这样优秀的文章已经帮助开发者们掌握了基本的选择器匹配优化原理. 我们从Steve Souders等大牛那里学到, 选择器是从右到左进行匹配的. 有的选择器匹配方式比较复杂所以应尽量避免使用. 比如说,后代选择器的匹配速度就比较慢,尤其是最右侧的选择器匹配了页面中大量元素的时候. 这些知识在早些年是很有用的. 但随着时间的发展, 感谢Antti Koivisto的努力, 很多选择器的效率问题我们已经无须过于担心了.

Antti致力于Webkit内核的改进工作. 他最近对CSS选择器的匹配机制进行了重要优化. 这些工作已经完成. 他表示:"我认为网页开发者已经无须对选择器进行优化了,那是浏览器引擎开发工程师的工作."

听起来很棒. 我喜欢以对文档结构更有意义的方式来使用选择器,选择器匹配效率优化这方面交给浏览器渲染引擎就好. 那么Antti到底对渲染引擎作了哪些优化呢? 事实上他对webkit渲染引擎的选择器匹配机制进行了多方面的优化. 我们来看看其中最主要的4项:

  1. 样式共享(Style Sharing)
  2. 规则散列(Rule Hashes)
  3. 祖先过滤器(Ancestor Filters)
  4. 快速路径(Fast Path)

    样式共享

样式共享使得浏览器允许样式列表中的元素与之前的相同元素重复相同的样式而不是重复计算渲染.

例如:


foo


bar


If the browser kernel has already calculated the style of the first

tag, it does not need to calculate the style of the second

tag again. This simple but smart improvement reduces browsing time A lot of work for the selector.

Rule Hashes

Now, we all know that selectors match from right to left, so the rightmost selector is very important. Rule hashing groups style sheets based on the rightmost selector. For example, the following style sheet will be divided into 3 groups:
a {}
div p {}
div p.legal {}
#sidebar a {}
#sidebar p {}
|a|p|p.legal|
|-|-|-|
|a {}|div p {} |div p.legal {}|
|-|-|-|
|#sidebar a {}|#sidebar p {}|

When the browser applies rule hashing, it Instead of parsing individual selectors in the entire style sheet, a much smaller range of possible matching groups are parsed. Rule hashing is also a small and simple improvement that can significantly reduce the need to parse individual HTML elements.

Ancestor Filters

Ancestor Filters are a little more complicated, they calculate the likelihood of a selector match. Therefore, when the element involved does not need to match an ancestor. The ancestor filter can quickly exclude relevant rules. Therefore, it detects descendant selectors and sub-selectors and matches based on class, ID, and tag. In the past, descendant selectors needed to be paid special attention to, and it needed to cycle through each ancestor node. To perform matching, Bloom filter can save this problem.

Bloom filter is a data structure that tests whether a specific selector is in a certain set. It looks very similar to selector matching, doesn't it? Bloom filters check whether a CSS rule matches a subset of the CSS rules for the element currently being tested. The great thing about Bloom filters is that positive false positives are possible, but negative false positives are not. That is, If a Bloom filter indicates that a selector does not match the current element, the browser will stop the query and advance to the next selector. This can save a lot of time. On the other hand, a Bloom filter indicates that the current selector does match, The browser will execute the normal matching strategy until the match is 100% certain. Complex stylesheets will lead to more errors, so it is recommended to keep your stylesheets to a reasonable length.

Ancestor filter speeds up descendants The matching speed of selectors and sub-selectors, it can also be used to divide other slower selectors into small sub-trees, and then the browser has only a small chance of needing to process those inefficient selectors.

Fast Path

Fast Path reimplements more general matching logic using a non-recursive, fully inline loop. It is used to match selectors containing any combination of the following:
1. Descendant selectors, sub-selectors, downwardly derived selectors
2. Selectors composed of tag selectors, id selectors, class selectors and attributes

The fast path has been improved a lot Performance of relational selectors. In fact, the overall performance of the selector has been improved by 25%, of which the performance of descendant selectors and subselects has been improved by 2 times, and it is also used for style matching in the querySelectorAll() method.

If so many selector performance have been improved, which ones are still slower?

Which ones are still slower?

Antti said, direct and indirect descendants Relational selectors are still slow. However, ancestor filters and rule hashing can reduce their impact because they are rarely matched. He also mentioned that there is a lot of room for Webkit to improve the parsing efficiency of pseudo-classes and pseudo-elements. But in any case, their parsing speed is much faster than Javascript's DOM manipulation. In fact, although there is still room for improvement, he said:

"From a style matching perspective, moderate use of all selectors will perform just Good."

I like hearing what he said. In short, if we control the style sheet to a normal size and use various selectors reasonably, we don't need to force ourselves to meet the past selector optimization standards. Thanks Antti.

Want to know more? Click on Paul Irish's presentation on CSS performance.

Original author Nicole Sullivan

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn