RouteSelectorMatchIndex scans every route's elements for :is()/:where() subjects and type-only leaves

Chiusa
#4,178 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Una pull request collegata è già stata integrata.

  • #4184 di @chubes4 — integrata

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
22/100
Tipo di issue
Refactoring
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
php
Ambito
performance

Direzione di ricerca

Start in RouteSelectorMatchIndex, comparing the two duplicated key-selection blocks in inertOutside and computeMatchedElements, and check how CssSelectorMatcher::matchesCompound and CssSelectorMatchCache are reached from applyAuthorStylesheetProjections. Linked PR #4184 already targets this change, so coordinate with it before starting. Done means finalize_artifact gets faster on the reproduction input while the compact WordPress site plan view hash stays byte-identical.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Problem

RouteSelectorMatchIndex narrows each selector arm to candidate elements by keys from the leaf compound's direct class, id or type only. Two common arm shapes get no useful key, so they are matched against every element of every route:

  1. Subject inside :is()/:where(). Projected author CSS wraps ids as :where(:is(#comp-x,.blocks-engine-editor-anchor-comp-x)). The leaf compound has no direct class or id, so candidates is null and inertOutside() scans the whole site per arm.
  2. Type-only leaf under a selective ancestor. :root .wp-block-navigation.blocks-engine-navigation-instance-14543b … div:not(...) keys on div, so computeMatchedElements() iterates every div on every route. It skips 28% of them as belonging to another route, even on routes that lack the ancestor class entirely.

Candidates are also indexed site-wide and filtered by owner afterwards, so each (arm, route) query pays for all routes' elements.

Evidence

Staged compose replayed natively (PHP 8.5) from a dumped SSI compose input, at trunk f97b2a53, for a 30-route Wix site (70,604 indexed elements):

  • finalize_artifact takes 340s and peaks at 3.9GB. The same step took 598s inside the importer's PHP-WASM runtime and was 57% of the whole import.
  • A 1s sampling profile puts 81% in applyAuthorStylesheetProjections, with a leaf of CssSelectorMatcher::matchesCompound.
  • inertOutside: 1,544 arms, 57.9M selector matches. The top arms each match all 70,604 or 68,385 elements, for example :where(.blocks-engine-attribute-46f13e08d94d-0)>:where(:is(#comp-msf3ikyq1,.blocks-engine-editor-anchor-comp-msf3ikyq1)):not(.be-c-0).
  • matchedElements: 144k calls, 73.4M candidate iterations (20.9M of them wrong-owner skips), and about 52M matches. 167 arms have ≥10k candidates, each 27,104 site-wide divs.
  • The CssSelectorMatchCache entries for those ~110M matches account for the memory.

Verified direction

A local prototype changes only RouteSelectorMatchIndex:

  • Per-route key index: keys[owner][key][id].
  • Shared candidates($parsed, $owner): one helper for both inertOutside and computeMatchedElements, replacing the two duplicated key-selection blocks. It does two things:
    • It takes the smallest key union for the leaf compound, now including an any (:is/:where) group whose every alternative's subject compound is keyed (the union of those alternatives' candidates).
    • It returns an empty set when any ancestor compound's keys are absent from that route.

On the same input this gives finalize_artifact 96s (from 340s) and peak 1.3GB (from 3.9GB), with a byte-identical compact WordPress site plan view hash (ec9d04cb…).

Expected

Selector-match work for an arm on a route is bounded by that route's elements carrying the arm's most selective key. Output stays byte-identical.

Part of #4171 (routes × shared selectors).

Lingua principale
PHP
Stelle
25
Fork
3
Merge medio
3h 25m
PR unite (30g)
935

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Automattic/blocks-engine

Tutte le issue di Automattic/blocks-engine

Issue simili

Altre issue su PHP

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.