Skip to content

Perf S1: size-gate continuous node effects on dense graphs (idle FPS 6.7→60)#68

Merged
mvalancy merged 1 commit into
developfrom
perf/large-graph-s1-effect-gate
Jun 15, 2026
Merged

Perf S1: size-gate continuous node effects on dense graphs (idle FPS 6.7→60)#68
mvalancy merged 1 commit into
developfrom
perf/large-graph-s1-effect-gate

Conversation

@mvalancy

Copy link
Copy Markdown
Member

Stage 1 of a measured, multi-stage large-graph performance effort

The Compute Core example graph (1000 nodes) felt sluggish. Profiling
(tests/diagnostics/large-graph-profile.spec.ts, new here) found it was 6.7
idle FPS at HIGH quality
— while nothing was moving.

Root cause (measured, not guessed)

Every node's .node-bg carries an SVG url(#node-drop-shadow) halo, and the
living-graph animations (node-breathe / node-ache / edge-flow) run
continuously. At 1000 nodes that's ~1000 filtered layers repainting every
frame. The LOW quality tier already strips these and hits 60 idle FPS on the
identical DOM
— so the effects, not the element count, were the idle killer.

Fix

Gate those effects off by graph size, independent of the quality tier: above
DENSE_GRAPH_NODE_THRESHOLD (150) nodes, .graph-container gets data-dense,
and new CSS (mirroring the existing LOW strips) drops the animations + drop-shadow
filter. Small graphs keep the full living-graph aesthetic at any tier.

Result (Compute Core, 1000n/1400e, HIGH)

metric before after
idle FPS 6.7 59.7
filter/blur els 1166 166

Drag (1.2) and zoom (3.2) FPS are per-tick work — addressed in the next stages
(viewport culling, zoom-handler throttle, simplified nodes at scale, spacing).

Verification

  • web typecheck: 0 errors
  • living-graph e2e 3/3 — small-graph effects unchanged
  • THE GATE (test:smoke) 5/5

🤖 Generated with Claude Code

… FPS 6.7→60)

Large graphs collapsed to ~7 idle FPS at HIGH quality while sitting still. Root
cause (measured): every node's .node-bg carries an SVG drop-shadow halo and the
living-graph animations (node-breathe / node-ache / edge-flow) run continuously,
so ~1000 filtered layers repaint every frame. LOW tier already strips these and
hits 60 idle FPS on the IDENTICAL DOM — proving the effects, not the node count,
were the idle killer.

Fix: gate those same effects off by graph SIZE, independent of the quality tier.
A graph with > DENSE_GRAPH_NODE_THRESHOLD (150) nodes sets data-dense on
.graph-container; new CSS rules (mirroring the LOW strips) drop the animations
and the drop-shadow filter. Small graphs keep the full living-graph aesthetic at
any tier — a user who picks HIGH still gets pretty small graphs and fast big ones.

Measured on the Compute Core example (1000 nodes / 1400 edges), HIGH quality:
  idle FPS  6.7 → 59.7    (filter/blur elements 1166 → 166)
Drag (1.2) and zoom (3.2) are per-tick work, addressed in following stages.

Adds tests/diagnostics/large-graph-profile.spec.ts (report-only baseline:
idle/drag/zoom FPS + DOM weight + data-dense confirmation).

Verified: web typecheck 0 errors; living-graph e2e 3/3 (small-graph effects
intact); THE GATE 5/5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 18.x & 20.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant