This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
Created attachment 162050 [details] self-profiler for getMainProject Method MainProjectManager.getMainProject() is called rather frequently in when doing Java development in NB. It is invoked per almost each user action to update UI (enabling/disabling of actions) and is invoked 4 times to start a unit test (2 * 2 threads, each invocation is around 120-150ms), see attached screenshot. Origin of this issue is (https://netbeans.org/bugzilla/show_bug.cgi?id=267969 - Running single simple unit test in debug takes 6+ seconds) and it may happen that it will be resolved by fixing of that issue (https://netbeans.org/bugzilla/show_bug.cgi?id=268027 - FileUtil.normalizedRef cache is cleaned too frequently). So ... what is going on inside: public Project getMainProject () { Project lastSelectedProject = lastSelectedProjectRef.get(); Project current = currentProject.get(); boolean isMain = isMainProject; if (isMain && lastSelectedProject != null && lastSelectedProject != current && ---> !isDependent(lastSelectedProject, current )) { <--- // If there's a main project set, but the current project has no // dependency on it, return the current project. return lastSelectedProject; } else { return current; } } implementation of isDependent() collects source roots for both projects and checks that way if one project depends on another private static boolean isDependent(Project p1, Project p2) { Set<URL> p1Roots = getProjectRoots(p1); Set<URL> p2Roots = getProjectRoots(p2); for (URL root : p2Roots) { Set<URL> dependentRoots = SourceUtils.getDependentRoots(root); for (URL sr : p1Roots) { if (dependentRoots.contains(sr)) { return true; } } } return false; } The problem here is that - collection of source roots is rather CPU consuming operation (because of FileUtil.normalizeFile()) - 'isDependent' status actually changes infrequently - when configuration of some project change (and that may not happen during the whole day). I think "the most correct" solution would be listening to changes in configurations of projects - and updating 'isDependent' status upon real changes. If that is technically hard to implement - caching of 'isDependent' status for few seconds would be sufficient (and refreshing it in 'only one background thread' - currently calculation of 'isDependent' is performed in parallel in each background tread which may need the 'getMainProject()'). For reference - one of the call stacks with MainProjectManager.getMainProject() ------------------------------------------------------------------------------- "Refresh Editor Context" at org.openide.filesystems.FileUtil.normalizeFileCached(FileUtil.java:1638) at org.openide.filesystems.FileUtil.normalizeFile(FileUtil.java:1629) at org.netbeans.modules.masterfs.filebasedfs.FileBasedURLMapper.getFileObjects(FileBasedURLMapper.java:98) at org.netbeans.modules.masterfs.MasterURLMapper.getFileObjects(MasterURLMapper.java:65) at org.openide.filesystems.URLMapper.findFileObject(URLMapper.java:213) at org.netbeans.api.java.source.SourceUtils.getDependentRoots(SourceUtils.java:790) at org.netbeans.api.java.source.SourceUtils.getDependentRoots(SourceUtils.java:770) at org.netbeans.modules.debugger.jpda.projectsui.MainProjectManager.isDependent(MainProjectManager.java:173) --> at org.netbeans.modules.debugger.jpda.projectsui.MainProjectManager.getMainProject(MainProjectManager.java:121) at org.netbeans.modules.debugger.jpda.projectsui.RunToCursorActionProvider.shouldBeEnabled(RunToCursorActionProvider.java:210) at org.netbeans.modules.debugger.jpda.projectsui.RunToCursorActionProvider.access$300(RunToCursorActionProvider.java:81)
Root cause for this bug is here: https://netbeans.org/bugzilla/show_bug.cgi?id=268045