Skip to content

Perf: switching to a MEMBER tab runs the parent PROGRAM's full validation concurrently with the member's - two heavy passes fight #359

Description

@msarson

Symptom ([357A BUILD] retest, 2026-07-14 — tab switch, no restart)

Switching from IBSCommon.clw to SelectJobNumber_IBSCommon.clw (a MEMBER of the IBSCommon PROGRAM, still open in another tab) runs TWO full async validation passes at the same time, interleaved on the single event loop:

  • SelectJobNumber (caller=onDidOpen, 2,643 tokens): total 10,967ms — discardedReturn 8,949ms, missingIncludes 9,278ms, undeclaredVar 2,507ms
  • IBSCommon (caller=crossFileUpdate, 68,486 tokens): total 9,846ms — undeclaredVar 9,042ms, missingConstants 9,060ms, missingImpl 1,960ms

Their perf lines interleave (11:21:17-11:21:26) and both finish ~simultaneously at +10-11s, each inflated by the other. Solo, SelectJobNumbers pass is far quicker (earlier warm runs: 2-3s); here it is dragged to ~11s by the parents concurrent 68k-token pass — for a tab the user just left.

Mechanism

onDidOpen validates only the opened doc. revalidateRelatedDocuments (stamps crossFileUpdate) fires from onDidChangeContent and re-validates OTHER open docs related to the changed one — a member change re-validates the open parent PROGRAM "so cross-file diagnostics clear" (server.ts:1516-1519). On tab activation the client emits a didChange, so the parent PROGRAM (IBSCommon, 68k tokens) gets a full pass concurrent with the member`s.

Two problems:

  1. No document-level serialization / priority. Startup responsiveness — audit fix plan (tracking issue with TODOs) #297 serialized validators WITHIN one document`s pass; two separate validateTextDocument calls (different docs) still interleave and contend — the Phase-A (Design: startup I/O schedule - sequential background lane + RED-shape freshness tiers (stop paying per-file verification on every start) #357) contention lesson, one level up. The VISIBLE document should be prioritized; background related-doc revalidation should not fight it.
  2. Possibly-unnecessary parent revalidation. Re-validating the parent PROGRAM makes sense when a member is EDITED (its cross-file diagnostics may shift). On a mere tab switch / open (no semantic change), it may be pure waste — worth gating on an actual content delta.

Fix direction (investigate-first)

  • Confirm the exact client trigger (spurious didChange on tab activation vs real edit); if no real delta, skip the related-doc revalidation.
  • Serialize document async passes (or prioritize the active/visible document and debounce/queue related-doc revalidation behind it) so two heavy passes never interleave.

Bonus data point (feeds #358)

IBSCommon`s undeclaredVar dropped 23,993ms (first open, cold) → 9,042ms here, because the in-memory chain index survived the session (DRIVEROPTIONS 18,491ms → 189ms). BUT it is still 9s WARM — dominated by the 51 unresolved template-equate names (findSymbol 6,001ms). So the #358 template-equate filter saves ~9s on EVERY validation of this file, not just the one-time cold build — filter > persistence for this path.

Surfaced by the #357 Phase-A retest. Related: #357 (background lane), #358 (chain-index/template-equate), #295 (off-thread).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions