Community
Participate
Working Groups
Build: 3.0 RC2 Test case: Start large workspace in Java perspective, two Java editors open on files in the workspace. Workspace contains 134 Java projects (Jeff's big self-hosting test workspace from 2.1.3). The profiler shows 2% of startup time is in JavaProject.computeExpandedClasspath. The method is called 118,680 times during startup. This is greater than n^2 where n is the number of projects in the workspace. I am not very familiar with the code, but it looks like DeltaProcessor.resetProjectCaches is called for each project classpath that gets initialized. This discards the current cached classpath, and eagerly recomputes it. Thus it looks like every project has its classpath computed for each project's classpath initialization. If resetProjectCaches did NOT eagerly recompute the classpath, perhaps it wouldn't need to be recomputed so many times for each project? OptimizeIt profiler output attached.
Created attachment 12090 [details] Profiler output of classpath computation
Relevant call trace: JavaProject.computeExpandedClasspath(ClasspathEntry, boolean, boolean, HashSet, ObjectVector, Map, Map) line: 422 JavaProject.computeExpandedClasspath(ClasspathEntry, boolean, boolean, HashSet, ObjectVector, Map, Map) line: 455 JavaProject.getExpandedClasspath(boolean, boolean, Map, Map) line: 1454 JavaProject.getExpandedClasspath(boolean) line: 1433 DeltaProcessor.addDependentProjects(IPath, HashSet) line: 277 DeltaProcessor.resetProjectCaches() line: 1703 DeltaProcessor.processResourceDelta(IResourceDelta) line: 1642 DeltaProcessor.resourceChanged(IResourceChangeEvent) line: 1783 DeltaProcessingState.resourceChanged(IResourceChangeEvent) line: 414 NotificationManager$2.run() line: 283 InternalPlatform.run(ISafeRunnable) line: 616 Platform.run(ISafeRunnable) line: 747 NotificationManager.notify(ResourceChangeListenerList$ListenerEntry[], IResourceChangeEvent, boolean) line: 277 NotificationManager.broadcastChanges(ElementTree, int, boolean) line: 151 Workspace.broadcastChanges(int, boolean) line: 172 Workspace.endOperation(ISchedulingRule, boolean, IProgressMonitor) line: 901 Workspace.run(IWorkspaceRunnable, ISchedulingRule, int, IProgressMonitor) line: 1683 NotificationManager$NotifyJob.run(IProgressMonitor) line: 38 Worker.run() line: 66
If this is not a performance issue please remove the performance keyword as we are now tracking these more closely.
Looks like a perfomance issue to me.
Adding my name to the cc list as we are now tracking performance issues more closely. Please remove the performance keyword if this is not a performance bug.
Changed SetClasspathOperation#updateAffectedProjects(IPath) to ignore projects than are not in the JavaModelCache as their namelookup cache doesn't need to be updated.
Are there outstanding work items for this bug?
Yes, I need to do some measurement to see the gain of my last change, and maybe optimize other call to computeExpandedClasspath.
Changed DeltaProcessor to compute a light weight dependency map (during DeltaProcessingState#initializeRoots()) instead of using getExpandedClasspath() which is expensive. In my monster workspace (more than 1000 plugins) resetting the project caches during delta processing used to take 85,000ms after a crash (0ms in case of no crash). It now takes 10ms after a crash (and still 0ms in case of no crash).
Verified for 3.1 M7 using build I20050513-0010.