Skip to content

perf(startup): defer editor and AI initialization#971

Merged
limityan merged 2 commits into
GCWing:mainfrom
limityan:yanzhn/defer-editor-ai-startup
May 30, 2026
Merged

perf(startup): defer editor and AI initialization#971
limityan merged 2 commits into
GCWing:mainfrom
limityan:yanzhn/defer-editor-ai-startup

Conversation

@limityan
Copy link
Copy Markdown
Collaborator

@limityan limityan commented May 30, 2026

Decision Status

This PR remains draft under #949, but the editor first-open regression called out in the previous PR description has now been mitigated with measured release-fast data.

Current data is positive for the target startup path and for the measured editor-heavy first-open paths. Remaining merge risk is mostly measurement rigor: the branch was rebased onto latest gcwing/main@18aa2df4, but the comparison baseline below is the existing #949 baseline (gcwing/main@978e079f) rather than a freshly rerun latest-main strict A/B baseline.

Refs #949

Summary

  • Move Monaco loader config, worker mapping, CSS loading, and resource checks from main.tsx into MonacoInitManager, so editor runtime work starts only when the editor is initialized.
  • Lazy-load editor-heavy surfaces (CodeEditor, DiffEditor, MarkdownEditor, ImageViewer, GitDiffEditor) from FlexiblePanel with a lightweight fallback.
  • After the shell is interactive and the startup splash has exited, schedule a low-priority idle editor warmup that preloads editor surfaces in slices, initializes Monaco, and syncs Monaco themes.
  • Start non-critical tool/context-menu initialization after bitfun:interactive-shell-ready instead of the earlier main-window signal, with a 10s watchdog fallback.
  • Remove root App AI auto-initialization and model-config subscription; AI initialization remains on explicit/on-demand service paths.
  • Keep the startup splash logo-only by default; show Loading workspace... below the logo only after 1800ms if workspace loading is still active, avoiding the short loading-text flash during normal startup.
  • Add performance contract coverage for startup bundle boundaries, deferred Monaco/theme behavior, editor first-open timing, warmup telemetry, and delayed splash loading feedback.

Measurement Method

  • Platform/build: Windows desktop release-fast.
  • Current PR head: 20d6a235, rebased on gcwing/main@18aa2df4.
  • Continuity baseline: gcwing/main@978e079f from perf(startup): continue reducing desktop startup and interactive shell readiness time #949's existing measurement set.
  • Runs: 5 repeated app launches per startup, long-session, code-editor, and Git-diff no-wait scenario; 5 code-editor explicit-warmup runs; 10 Git-diff explicit-warmup runs after one small outlier in the first 5-sample set.
  • Startup and long-session timing: tests/e2e/specs/performance/startup-session-perf.spec.ts.
  • Editor first-open timing: tests/e2e/specs/performance/editor-first-open-perf.spec.ts.
  • Long-session fixture: 80 sessions, latest long session has 80 turns; first render measures latest visible content, then full hydrate.
  • Editor first-open measures event trigger to Monaco DOM ready. It intentionally isolates deferred editor/rendering cost, not file-tree click latency or Git status refresh.

Runtime Results

Cold Startup, p50

Metric Baseline This PR Delta
first_script_eval 1179.0 ms 601.1 ms -577.9 ms (-49.0%)
main_window_shown 1309.5 ms 711.3 ms -598.2 ms (-45.7%)
interactive_shell_ready 1720.4 ms 1059.8 ms -660.6 ms (-38.4%)
non_critical_init_done 1667.2 ms 1315.9 ms -351.3 ms (-21.1%)

Startup target result: positive on the measured release-fast head data.

First Open Of Long Historical Session, p50

Metric Baseline This PR Delta
Backend restore 45.6 ms 41.5 ms -4.1 ms (-9.0%)
Latest frame after hydrate 45.7 ms 46.5 ms +0.8 ms (+1.8%)
Initial hydrate 105.9 ms 102.9 ms -3.0 ms (-2.8%)
Full hydrate 51.5 ms 52.7 ms +1.2 ms (+2.3%)

Long-session result: neutral to slightly positive, with the remaining regressions under 2 ms p50 in this run.

First Editor-Heavy Interaction, p50

Scenario Baseline Previous PR before warmup This PR no explicit wait This PR after warmup wait
First code editor open 384.1 ms 503.7 ms 207.4 ms 203.4 ms
First Git diff editor open 398.6 ms 526.9 ms 283.7 ms 271.2 ms

Editor result: the previous first-use regression is mitigated. Compared with the previous PR measurement, code-editor p50 drops by 296.3 ms and Git-diff p50 drops by 243.2 ms. Compared with the continuity baseline, code-editor p50 improves by 176.7 ms (-46.0%) and Git-diff p50 improves by 127.4 ms (-32.0%) in the explicit-warmup path.

Background Editor Warmup Cost

Scenario Samples Warmup completed before trigger Warmup duration p50
Code editor, no explicit wait 5 5/5 235.6 ms
Code editor, explicit wait 5 5/5 237.0 ms
Git diff, no explicit wait 5 5/5 226.7 ms
Git diff, explicit wait 10 10/10 230.4 ms

This work is deliberately scheduled after splash exit and split across idle slices. It still consumes post-startup idle time and is not free.

Bundle / Parse-Pressure Evidence

Measured earlier with pnpm --dir src/web-ui run build on this PR line.

Scenario Entry JS Monaco runtime markers Root AI hook marker
gcwing/main@978e079f 8,298,942 bytes present (Click to toggle color options, editor.action.showHover) present (useAIInitialization)
This PR line 4,294,694 bytes removed removed

Net entry JS reduction: 4,004,248 bytes / 48.25%.

Risks / Functional Impact

  • Latest-main strict A/B was not rerun after the rebase. The current head data is real repeated release-fast data, but final merge should not pretend it is a strict latest-main A/B comparison.
  • Users who open an editor before the idle warmup finishes can still pay partial cold cost. The current measured no-wait runs completed warmup before trigger, so this edge remains a residual risk rather than proven neutral.
  • Background editor warmup costs about 230 ms total in idle slices. It improves likely first editor open, but it can still contend with user activity if the browser grants idle time aggressively.
  • Root AI initialization is no longer automatic at app mount. Focused tests pass, but manual AI-entry validation is still useful before marking ready.
  • Delaying non-critical initialization behind bitfun:interactive-shell-ready reduces startup pressure but can delay tool/context-menu availability if the readiness event is late or missed; the watchdog caps this at 10s.
  • Startup workspace loading text is intentionally delayed to 1800ms; slower startups still show a loading hint below the logo, while normal startup paths stay logo-only.

Current Decision

Do not merge solely on bundle-size or architecture arguments. With the current release-fast data, this PR now has a measured user-facing performance result:

  • Startup p50 improves by 351-661 ms across the measured marks.
  • Long-session first-open stays neutral in p50.
  • First editor-heavy interactions improve relative to both the previous PR measurement and the continuity baseline after the background warmup mitigation.

The remaining blocker is whether we require a fresh latest-main strict A/B run before marking the draft ready.

Verification

  • pnpm --dir src/web-ui run test:run src/tools/editor/services/MonacoStartupWarmup.test.ts src/app/startup/startupPerformanceContract.test.ts src/app/components/SplashScreen/SplashScreen.test.tsx src/infrastructure/theme/integrations/MonacoThemeSync.test.ts src/shared/utils/startupTaskScheduling.test.ts src/infrastructure/services/api/aiService.test.ts
  • pnpm run type-check:web
  • pnpm run i18n:audit
  • pnpm run check:repo-hygiene
  • pnpm run desktop:build:release-fast
  • git diff --check gcwing/main...HEAD
  • BITFUN_E2E_APP_MODE=release-fast pnpm --dir tests/e2e run test:perf repeated 5 times
  • BITFUN_E2E_EDITOR_SCENARIO=code-editor pnpm --dir tests/e2e exec wdio run ./config/wdio.conf.ts --spec ./specs/performance/editor-first-open-perf.spec.ts repeated 5 times without explicit warmup wait and 5 times with explicit warmup wait
  • BITFUN_E2E_EDITOR_SCENARIO=git-diff pnpm --dir tests/e2e exec wdio run ./config/wdio.conf.ts --spec ./specs/performance/editor-first-open-perf.spec.ts repeated 5 times without explicit warmup wait and 10 times with explicit warmup wait

@limityan limityan force-pushed the yanzhn/defer-editor-ai-startup branch 2 times, most recently from de70290 to e1895e6 Compare May 30, 2026 09:42
@limityan limityan marked this pull request as draft May 30, 2026 09:43
@limityan limityan force-pushed the yanzhn/defer-editor-ai-startup branch from c89dfd3 to ea1ac6a Compare May 30, 2026 10:57
@limityan limityan force-pushed the yanzhn/defer-editor-ai-startup branch from ea1ac6a to 20d6a23 Compare May 30, 2026 12:01
@limityan limityan marked this pull request as ready for review May 30, 2026 12:30
@limityan limityan merged commit 065cd8d into GCWing:main May 30, 2026
4 checks passed
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