Optimize stylesheet matching with class-based indexing:

Index class-anchored selectors by one mandatory class hash so widgets
  only evaluate rules associated with their own classes instead of
  scanning every class-only rule in the global bucket.

  Preserve selector correctness by validating the complete rule after
  candidate lookup, and retain stylesheet source order across independent
  index buckets for equal-specificity cascade resolution.

  Update index clearing, copying, marker removal, and style insertion
  paths. Add focused candidate coverage and a legacy full-scan benchmark,
  showing a 63% lookup-time reduction on a class-heavy stylesheet.
This commit is contained in:
Martín Lucas Golini
2026-07-10 19:31:15 -03:00
parent 3e29da6a2e
commit d29dbb1cc1
9 changed files with 201 additions and 10 deletions
@@ -631,6 +631,28 @@ Ensure class mutation APIs update hashes correctly.
# Phase 6: Add Class-Based Stylesheet Index
**Status: Implemented**
## Implementation State
- `StyleSheet` maintains a class-hash index in addition to the existing global, tag, ID, and
tag+ID index.
- Each style is owned by exactly one candidate bucket. The priority is ID/tag+ID, one rightmost
class anchor, tag, then global, so candidate collection does not require a per-element visited
allocation.
- Selector rules expose their sorted class hashes and currently select the first hash as the class
anchor.
- Class index state participates in clear, copy assignment, marker-based removal, and normal style
insertion paths.
- Per-stylesheet source-order metadata is used as the secondary sort key after specificity. This
preserves CSS cascade order when candidates originate from different index buckets.
- A focused candidate test covers global, tag, class-only, compound-class, tag+class, ID+class,
and unrelated-class rules.
- `Benchmark.CSSClassIndexLookup` exercises 1,024 class rules, of which 64 share a class with the
target widget. Across ten release runs, the legacy full scan had a 124.1 ms median and indexed
lookup had a 45.7 ms median for 20,000 lookups: a 63.2% reduction, or approximately 2.7x faster.
- The full release suite passes 735 tests with one skipped test.
## Motivation
This is expected to be the largest real-world win.