Skip to content

ENG-1579: Fix plugin init performance#915

Open
sid597 wants to merge 5 commits intoeng-1470-test-dual-read-with-flag-on-and-fix-gapsv2from
eng-1579-performance-plugin-take-multiple-seconds-on-initial-load-and
Open

ENG-1579: Fix plugin init performance#915
sid597 wants to merge 5 commits intoeng-1470-test-dual-read-with-flag-on-and-fix-gapsv2from
eng-1579-performance-plugin-take-multiple-seconds-on-initial-load-and

Conversation

@sid597
Copy link
Copy Markdown
Collaborator

@sid597 sid597 commented Mar 26, 2026

The regression was caused by repeated dual-read validation work during startup, not
by block props themselves; we cached that path and fixed invalidation, which brought
init from ~20s down to ~1.15s. This is the right migration-phase fix, and the long-
term cleanup is to delete dual-read entirely.

[DG Perf] initPostHog: 331.548ms                                                                                                                                            
  [DG Perf] initFeedbackWidget: 0.052ms                                                                                                                                     
  [DG Perf] initializeDiscourseNodes: 0.810ms                                                                                                                                 
  [DG Perf] refreshConfigTree: 413.464ms                                                                                                                                      
  [DG Perf] addGraphViewNodeStyling: 0.242ms                                                                                                                                  
  [DG Perf] registerCommandPaletteCommands: 0.584ms                                                                                                                           
  [DG Perf] createSettingsPanel: 0.100ms                                                                                                                                      
  [DG Perf] registerSmartBlock: 0.085ms                                                                                                                                     
  [DG Perf] setInitialQueryPages: 0.263ms                                                                                                                                     
  [DG Perf] styles injection: 0.137ms                                                                                                                                         
  [DG Perf] observer: pageTitleObserver: 0.153ms                                                                                                                            
  [DG Perf] observer: queryBlockObserver: 2.748ms                                                                                                                             
  [DG Perf] observer: nodeTagPopupButtonObserver: 0.049ms                                                                                                                     
  [DG Perf] observer: suggestiveOverlaySetup: 0.037ms                                                                                                                       
  [DG Perf] observer: graphOverviewExportObserver: 0.046ms                                                                                                                    
  [DG Perf] observer: imageMenuObserver: 0.017ms                                                                                                                              
  [DG Perf] observer: pageRefObserverSetup: 0.007ms                                                                                                                         
  [DG Perf] observer: listenersAndTriggerSetup: 23.911ms                                                                                                                      
  [DG Perf] observer: leftSidebarObserver: 1.179ms                                                                                                                            
  [DG Perf] initObservers: 30.171ms                                                                                                                                         
  [DG Perf] installDiscourseFloatingMenu: 0.410ms                                                                                                                             
  [DG Perf] initSchema > ensurePageExists: 1.369ms                                                                                                                            
  [DG Perf] initSchema > buildBlockMap: 0.623ms                                                                                                                             
  [DG Perf] initSchema > ensureBlocksExist: 0.209ms                                                                                                                           
  [DG Perf] initSchema > ensureLegacyConfigBlocks: 2.327ms                                                                                                                    
  [DG Perf] initSchema > initializeSettingsBlockProps: 3.490ms                                                                                                              
  [DG Perf] initSchema > initSettingsPageBlocks: 8.196ms                                                                                                                      
  [DG BlockProps Migration] graph-level: skipped (already migrated)                                                                                                         
  [DG Perf] initSchema > migrateGraphLevel: 305.434ms                                                                                                                         
  [DG Perf] initSchema > initDiscourseNodePages: 71.149ms                                                                                                                     
  [DG BlockProps Migration] personal: skipped (already migrated)                                                                                                            
  [DG Perf] initSchema > migratePersonalSettings: 0.091ms                                                                                                                     
  [DG Perf] initSchema: 385.023ms                                                                                                                                             
  [DG Perf] setupPullWatchOnSettingsPage: 0.358ms                                                                                                                           
  [DG Perf] Total init: 1163.951ms                                

Open with Devin

Summary by CodeRabbit

Release Notes

  • Refactor

    • Updated settings dialog invocation from overlay-based rendering to direct function calls.
    • Introduced caching mechanisms for settings accessors, discourse nodes, relations, and configuration state with version tracking.
    • Implemented selective cache invalidation during settings updates and initialization.
    • Added performance timing tracking within the settings dialog.
  • Chores

    • Added initialization timing metrics collection to the startup sequence.

…paths

Cache isNewSettingsStoreEnabled(), getFeatureFlags(), getGlobalSettings(),
getPersonalSettings(), and all legacy setting readers to avoid redundant
Roam DB queries during init. Cache getDiscourseNodes/Relations and fix
findDiscourseNode default param that evaluated getDiscourseNodes() before
cache check. Add console.time instrumentation for ongoing diagnostics.

Init: 27s → 1.1s on megacoglab. Settings panel: 17s → 11ms.
@linear
Copy link
Copy Markdown

linear bot commented Mar 26, 2026

@supabase
Copy link
Copy Markdown

supabase bot commented Mar 26, 2026

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

devin-ai-integration[bot]

This comment was marked as resolved.

…ersion-based invalidation

- Remove all console.time instrumentation, replace with single
  performance.now() total init log
- Rename _underscore cache variables to camelCase (drop eslint-disable)
- Add configCacheVersion module for cross-module cache staleness
  without circular imports
- Remove redundant invalidateNewSettingsStoreCache (shared watcher
  path already handles it)
- Add TODO(ENG-1471) on legacy dual-read caches
- Rename render → openSettingsDialog, measure settings open time
  via requestAnimationFrame
@sid597
Copy link
Copy Markdown
Collaborator Author

sid597 commented Mar 27, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

✅ Actions performed

Full review triggered.

devin-ai-integration[bot]

This comment was marked as resolved.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

📝 Walkthrough

Walkthrough

The PR introduces a caching infrastructure for settings and discourse graph structures, with cache invalidation integrated into settings initialization, pull-watch updates, and full config refresh. Performance timing is added to track dialog opening and overall extension startup duration.

Changes

Cohort / File(s) Summary
Settings Dialog Enhancement
apps/roam/src/components/LeftSidebarView.tsx, apps/roam/src/components/settings/Settings.tsx
Replaced renderOverlay invocation with new openSettingsDialog function that captures performance.now() as openedAt. Added optional openedAt prop to SettingsDialog with useEffect logging elapsed time to console. Kept render as backward-compatible alias.
Settings Accessor Caching
apps/roam/src/components/settings/utils/accessors.ts
Introduced module-level caches for feature flags, global/personal settings, discourse nodes, and block-props. Replaced per-call legacy settings reads with cache-backed builders (buildLegacyPersonalSettings, buildLegacyGlobalSettings). Added invalidateSettingsAccessorCaches() and wired it into setBlockPropAtPath; cached settings block UID resolution via getTopLevelSettingsBlockUid.
Cache Invalidation Wiring
apps/roam/src/components/settings/utils/init.ts, apps/roam/src/components/settings/utils/pullWatchers.ts, apps/roam/src/utils/refreshConfigTree.ts
Added invalidateSettingsAccessorCaches() calls after schema migration and on successful pull-watch updates. Integrated cache invalidation into refreshConfigTree before translator re-registration.
Discourse Graph Caching
apps/roam/src/utils/getDiscourseNodes.ts, apps/roam/src/utils/getDiscourseRelations.ts
Added module-level caching with version tracking for both discourse nodes and relations. Introduced invalidateDiscourseNodesCache() and invalidateDiscourseRelationsCache() functions. Cache invalidation triggered via getConfigCacheVersion() on config changes.
Cache Version Management
apps/roam/src/utils/configCacheVersion.ts
New module maintaining numeric configCacheVersion initialized to 0. Exports getConfigCacheVersion() and bumpConfigCacheVersion() to manage global cache versioning.
Discourse Node Resolution
apps/roam/src/utils/findDiscourseNode.ts
Changed parameter defaulting from initialization-time to runtime: nodes parameter now resolves via const resolvedNodes = nodes ?? getDiscourseNodes() instead of default parameter assignment.
Startup Instrumentation
apps/roam/src/index.ts
Added initStartedAt = performance.now() at extension startup and performance log after async initialization. Adjusted blank lines throughout initialization sequence without changing control flow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #33: Modifies SettingsDialog component in Settings.tsx with additional props and keyboard shortcut integration, overlapping with this PR's dialog enhancement changes.
  • PR #637: Updates findDiscourseNode parameter handling in apps/roam/src/utils/findDiscourseNode.ts, directly overlapping with this PR's runtime parameter resolution changes.
  • PR #669: Adds cached accessor functions to apps/roam/src/components/settings/utils/accessors.ts, directly aligned with this PR's core caching infrastructure additions.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main objective of the pull request: fixing plugin initialization performance through caching strategies.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]

This comment was marked as resolved.

@sid597 sid597 requested a review from mdroidian March 28, 2026 03:14
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