Performance: O(n²) selector matching with descendant combinators
Open
@lukehoban is already working on this.
Since Mar 24, 2026.
performance
- Dominant language
- Go
- Stars
- 1
- Forks
- 2
- PR merge metrics
- No merged PRs in 30d
Description
Description
CSS selector matching in style/style.go has O(n²) complexity when dealing with descendant selectors on large documents.
Location
style/style.go:205-275-matchRules(),matchesSelector(),matchesDescendant()
Problem
matchRules()iterates over ALL rules × ALL selectors for every elementmatchesDescendant()recursively walks ancestors for each selector with descendant combinators- For each element, this triggers O(ancestors) walks per rule
Complexity: O(elements × rules × selectors × tree_depth)
Suggested Improvements
- Index selectors by tag name/class/ID - Create lookup maps during stylesheet parsing to quickly filter rules that could match
- Cache selector matching results - Memoize matches for identical elements
- Bloom filter for ancestors - Use bloom filters to quickly reject non-matching descendant selectors
- Right-to-left matching with early exit - Already partially implemented, but could be optimized further
Impact
Large pages like Hacker News (many <tr>, <td> elements) will experience significant slowdowns during style computation.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.