lukehoban / lukehoban/browser

Performance: O(n²) selector matching with descendant combinators

Open
#79 0 comments 1 reaction 2 assignees View on GitHub

@lukehoban is already working on this.

Since Mar 24, 2026.

  • #88 by @copilot-swe-agent — open
  • #93 by @copilot-swe-agent — open
  • #94 by @copilot-swe-agent — open
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

  1. matchRules() iterates over ALL rules × ALL selectors for every element
  2. matchesDescendant() recursively walks ancestors for each selector with descendant combinators
  3. For each element, this triggers O(ancestors) walks per rule

Complexity: O(elements × rules × selectors × tree_depth)

Suggested Improvements

  1. Index selectors by tag name/class/ID - Create lookup maps during stylesheet parsing to quickly filter rules that could match
  2. Cache selector matching results - Memoize matches for identical elements
  3. Bloom filter for ancestors - Use bloom filters to quickly reject non-matching descendant selectors
  4. 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.