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

Cerrado
#4,178 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Ya se ha fusionado un pull request relacionado.

  • #4184 de @chubes4 — fusionado

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
22/100
Tipo de issue
Refactorización
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
php
Área
performance

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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).

Lenguaje dominante
PHP
Estrellas
25
Forks
3
Merge medio
2 h 23 min
PR fusionados (30 d)
942

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de Automattic/blocks-engine

Todos los issues de Automattic/blocks-engine

Issues similares

Más issues de PHP

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.