Schema view lockup from per-type Cytoscape style selectors in useGraphStyles
- Dominant language
- TypeScript
- Stars
- 481
- Forks
- 108
- Avg merge
- 6d 8h
- Merged PRs (30d)
- 5
Description
## Symptom
With very large label sets (repro: ~10k node labels + ~10k edge labels), the schema view pins the main thread and never renders — even after the icon fan-out fix (#2103). A performance trace attributes 87.6% self-time to Cytoscape's style engine (`getPropertiesDiff` + `getContextStyle`); the layout is never reached (0.3 ms).
## Root cause
`createGraphStyles` (`useGraphStyles.ts`) emits one selector per type — `node[type="…"]` and `edge[type="…"]` — so ~20k style contexts. Cytoscape resolves each element's style by scanning all contexts, making style application O(elements × contexts) ≈ 4×10⁸. Compounding it, `useManageStyles`'s effect is keyed on a `styles` object with fresh identity every render, so the multi-second recompute can re-fire and never settle.
## Evidence
Headless benchmark, per-type selectors vs. a single `data()` mapper rule, forcing per-element resolution:
| n (each of node + edge types) | contexts | resolve |
|---|---|---|
| 1,000 | 2,002 | 437 ms |
| 3,000 | 6,002 | 3,622 ms |
| 10,000 | 20,002 | ~100 min |
| 10,000 *(data-mapper)* | **2** | **324 ms** |
## Fix
Two independently shippable phases:
1. **Stabilize the effect** — memoize the `styles` object identity so `useManageStyles` applies once instead of re-firing the recompute.
2. **Data-mapper conversion** — precompute each element's resolved style values onto `ele.data()` (`ge_*`) at the element-enrichment seam and emit one `node` rule + one `edge` rule using `data(...)`, mirroring the existing `node[__iconUrl]` mapper. Contexts drop ~20k → ~2; `cy.style()` becomes O(elements). Extends #1725 (which validates the architecture for `background-color`) to all per-type properties.
Per-element logic that must move out of the style loop into precompute: the `isDark()` label text-color pick, the `line-dash-pattern`/`lineStyle` remap, and shape coercion (ADR `20260710-coerce-retired-round-polygon-shapes`).
Regression guard: assert style-context count stays O(1) regardless of type count.
## Related
Umbrella #2091 · caused-with #2103 · architecture #1725 · epic #1677 · spike #1797
> [!IMPORTANT]
> Internal only — this issue is maintained by the core team and is not accepting external contributions.
Contributor guide
Assessment
This issue has not been assessed yet.