fix: mitigate high CPU and thread explosion in large multi-module workspaces#1895
Open
gaogage wants to merge 1 commit into
Open
fix: mitigate high CPU and thread explosion in large multi-module workspaces#1895gaogage wants to merge 1 commit into
gaogage wants to merge 1 commit into
Conversation
…erver Three changes to address severe CPU/memory issues in large multi-module workspaces (500-900% CPU, CachedThreadPool thread explosion, NPE errors): 1. CompositeASTVisitor: add null guards in delegateVisit() and endVisit() loops to prevent NPE when a null visitor is present in the list. Fixes the recurring "astVisitor is null" NPE from JdtCodeActionHandler. 2. Replace Executors.newCachedThreadPool() with bounded newFixedThreadPool() in three locations to prevent unlimited thread creation during indexing: - SpringIndexCommands (UI-triggered commands): 4 threads - CompilationUnitCache (CU creation): availableProcessors threads - ModulithService (metadata processing): 4 threads This prevents the observed pool-11 explosion to 500+ threads. 3. SpringMetamodelIndex: add O(1) docUriToDocument ConcurrentHashMap cache to avoid full BFS traversal of the entire index tree on every getDocument() call. Cache is maintained in updateElements(), removeElements(), and removeProject(). Falls back to traversal for pre-existing elements not yet in cache. Refs: spring-projects#1894
Contributor
|
I'd try to the cached thread pool but limited the max number of threads a small reasobale number: new ThreadPoolExecutor(0, <REASONABLE_SMALL_MAX_THREADS>,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes three compounding issues that cause Spring Boot Language Server to consume 500-900% CPU in large multi-module Maven workspaces (25+ projects).
Closes #1894
Changes
1. CompositeASTVisitor: null guard against NPE (1 file)
Added null checks in
delegateVisit()andendVisit()loops to prevent the recurring"astVisitor is null"NPE fromJdtCodeActionHandler. When a null visitor is present in the list, the iteration now safely skips it instead of crashing. This NPE occurred 150+ times during a typical session.2. CachedThreadPool → FixedThreadPool (3 files)
Replaced
Executors.newCachedThreadPool()with boundednewFixedThreadPool()to prevent unlimited thread creation during project indexing:SpringIndexCommands.java:62newCachedThreadPool()newFixedThreadPool(4)CompilationUnitCache.java:86newCachedThreadPool()newFixedThreadPool(availableProcessors)ModulithService.java:114newCachedThreadPool()newFixedThreadPool(4)This eliminates the observed pool-11 explosion to 500+ threads (pool-11-thread-536), each consuming 60-100 CPU-seconds.
3. SpringMetamodelIndex: O(1) document lookup cache (1 file)
Added a
ConcurrentHashMap<String, DocumentElement> docUriToDocumentcache to avoid the full BFS traversal of the entire index tree on everygetDocument()call. The cache is maintained transactionally inupdateElements(),removeElements(), andremoveProject(). Falls back to traversal for pre-existing elements not yet in cache.This address the most impactful performance issue: each VSCode UI interaction (file tab switch, Spring Explorer refresh) triggered
getBeansOfDocument()→getDocument()→ full BFS walk of all 26 projects' bean trees.Observed Impact
In a workspace with 26 Spring Boot Maven modules:
Testing