Skip to content

Optimize performance and fix plugin loading logic#53

Merged
MarcosBrendonDePaula merged 2 commits intomainfrom
claude/optimize-core-plugins-joOyq
Feb 12, 2026
Merged

Optimize performance and fix plugin loading logic#53
MarcosBrendonDePaula merged 2 commits intomainfrom
claude/optimize-core-plugins-joOyq

Conversation

@MarcosBrendonDePaula
Copy link
Copy Markdown
Collaborator

Summary

This PR improves performance across multiple systems through caching, algorithmic optimization, and memory management, while fixing critical issues in plugin dependency resolution and resource cleanup.

Key Changes

Vite Plugin Static File Serving (core/plugins/built-in/vite/index.ts)

  • Pre-scan file system at startup: Replaced per-request file lookups with a one-time recursive directory scan stored in a Map for O(1) lookup performance
  • Implement Bun.file() handle caching: Avoid recreating file handles on repeated requests
  • Add aggressive caching for hashed assets: Files matching the pattern .[0-9a-f]{8,}.\w+$ (content-hashed) now return Cache-Control: public, max-age=31536000, immutable headers
  • Optimize URL parsing: Replaced full URL object parsing with manual string operations to avoid unnecessary allocations
  • Cache isDevelopment() result: Moved isDevelopment() call to module load since NODE_ENV doesn't change at runtime

Plugin Registry Load Order (core/plugins/registry.ts)

  • Refactor topological sort algorithm: Replaced simple DFS-based ordering with Kahn's algorithm that respects both dependency constraints and priority levels
  • Separate cycle detection from ordering: Cycle detection now runs first via DFS, then ordering uses a priority-aware group selection approach
  • Preserve priority within dependency levels: Plugins at the same dependency depth are now sorted by priority (highest first) before being added to the load order

Plugin Manager Hook Execution (core/plugins/manager.ts)

  • Fix timeout cleanup: Add clearTimeout() in finally block to prevent timer leaks when hooks complete before timeout
  • Optimize enabled plugin lookup: Replace Array.includes() with Set.has() for O(1) lookup instead of O(n)

Monitoring Plugin (core/plugins/built-in/monitoring/index.ts)

  • Cache CPU count: Move os.cpus().length outside the collection loop since CPU count is immutable at runtime
  • Implement histogram memory bounds: Cap histogram values at 1000 entries, keeping the most recent half when limit is exceeded to preserve statistical relevance while preventing unbounded memory growth

Plugin Discovery (core/plugins/discovery.ts)

  • Defer instantiation: Change pluginDiscovery from eager singleton to lazy-initialized function getPluginDiscovery() to avoid side effects at module load
  • Mark as deprecated: Add deprecation notice since PluginRegistry now handles discovery directly

Plugin Config Manager (core/plugins/config.ts)

  • Share config manager instance: Create a single sharedConfigManager instance for deepMerge() and validateSchema() utilities since the manager is stateless

Plugin Module Resolver (core/plugins/module-resolver.ts)

  • Fix cache method call: Correct typo where this.cacheSet() should be this.resolveCache.set()

Notable Implementation Details

  • The Vite static file serving now uses a startup-time directory scan that runs once in production, making subsequent requests extremely fast
  • The plugin load order algorithm now correctly handles complex dependency graphs while respecting priority, fixing cases where high-priority plugins could be loaded before their dependencies
  • Memory management improvements prevent unbounded growth in long-running monitoring collection

https://claude.ai/code/session_017p98YBiey4Jb8HaLeuLNAQ

- Fix infinite recursion in PluginModuleResolver.cacheSet() (stack overflow on first cache write)
- Fix timeout timer leak in PluginManager.executePluginHook() (clearTimeout after race)
- Replace O(n) Array.includes() with Set lookup for enabled plugins check
- Replace broken topological sort + .sort() with Kahn's algorithm that respects
  both dependency constraints and priority within each dependency level
- Cache isDevelopment() at module load in vite plugin (avoids per-request eval)
- Cap histogram values array at 1000 entries in monitoring plugin (prevents unbounded memory growth)
- Cache os.cpus().length in monitoring system metrics collector (avoids expensive syscall per interval)
- Reuse shared DefaultPluginConfigManager instance in createPluginUtils()
- Defer PluginDiscovery singleton instantiation (unused, was eagerly allocated at import)

https://claude.ai/code/session_017p98YBiey4Jb8HaLeuLNAQ
- Pre-scan all build output files at startup into a Map for O(1) lookups
  (replaces per-request statSync syscalls that blocked the event loop)
- Cache Bun.file() handles to avoid re-creating them on repeated requests
- Pre-resolve index.html once for SPA fallback (was recalculated per request)
- Fast pathname extraction without full URL parse (string ops vs new URL())
- Conditional decodeURIComponent only when '%' is present
- Add Cache-Control: immutable for hashed assets (e.g. app.abc123.js)

https://claude.ai/code/session_017p98YBiey4Jb8HaLeuLNAQ
@MarcosBrendonDePaula MarcosBrendonDePaula merged commit 359d166 into main Feb 12, 2026
11 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.

2 participants