Community
Participate
Working Groups
As more and more build dependencies (especially for circular dependencies) are added to a project, when editing the build path of a project properties (even for other projects that references this current project), the waiting time for the GUI to come up increases exponentially.
Can you please comment and move to Core if appropriate. In general I thought we don't support circular build dependencies.
Can you provide exact steps to reproduce ?
1) start IDE with and empty workspace 2) create an EAR project 3) create 10 EJB projects 4) for each EJB project created in (3), make its build path to point to the rest 9; ie. every project dependents on every project. 5) right click on any EJB project and choose Properties 6) select Java Build Path This takes 45 seconds to come up 7) select Project tab and select or unselect each dependent project Each selection of checkbox takes 25 seconds to come back
Reproduced with 8 normal Java Projects. With 7 fully inter-connected projects, the performance is still acceptable. With 8, you start to see delays in the 1-3 second range. With 9, the delays become 3-10 seconds to add the new project to each existing project's project dependency list.
The first required fix is to the method JavaProject.hasClasspathCycle (IClasspathEntry[] entries) Instead of computing all the cycle participants and then testing if the collection is not empty, we only need to find the first project involved in a cycle to answer true. I inlined the method updateCycleParticipants(...) and was able to add several additional projects to the fully connected cycle, before another performance problem surfaced at 11 projects.
Actually both problem areas are addressed if we change the classpath loop in JavaProject.updateCycleParticipants() to test if the current project and the next project are already included in the cycle before looping: if (!cycleParticipants.contains(this) && !cycleParticipants.contains(project)) project.updateCycleParticipants(null, visited, cycleParticipants, workspaceRoot); Philippe: OK?
Released into current development stream. The added line was: if (!cycleParticipants.contains(this) || !cycleParticipants.contains(project)) so if either the current project or the next project are NOT included in the cycleParticipants then we do need to recurse to the next project... otherwise we can skip it.
*** Bug 23375 has been marked as a duplicate of this bug. ***
Previous fix did not work for case where segments are shared in between cycles. Need better fix, and backport to 2.0.2
Scenario where it doesn't work: P0 -> P2 -> P3 -> P1 -> P0 P0 -> P4 -> P5 -> P1 In this case, it does not report the cycle P0, P1, P4, P5
Proposed fix from Kent: /** * If a cycle is detected, then cycleParticipants contains all the project involved in this cycle (directly), * no cycle if the set is empty (and started empty) */ public void updateCycleParticipants(IClasspathEntry[] preferredClasspath, ArrayList visited, HashSet cycleParticipants, IWorkspaceRoot workspaceRoot){ visited.add(this); try { IClasspathEntry[] classpath = preferredClasspath == null ? getResolvedClasspath(true) : preferredClasspath; for (int i = 0, length = classpath.length; i < length; i++) { IClasspathEntry entry = classpath[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT){ String projectName = entry.getPath ().lastSegment(); JavaProject project = (JavaProject) JavaCore.create(workspaceRoot.getProject(projectName)); int index = visited.indexOf(project); if (index == -1 && cycleParticipants.contains(project)) index = visited.indexOf (this); // another loop in the cycle exists if (index >= 0) { // only consider direct participants inside the cycle for (int size = visited.size(); index < size; index++) cycleParticipants.add (visited.get(index)); } else { project.updateCycleParticipants (null, visited, cycleParticipants, workspaceRoot); } } } } catch(JavaModelException e){ } visited.remove(this); }
With latest version: Dense cycle check (5 participants) : 921 ms Dense cycle check (10 participants) : 2250 ms Dense cycle check (20 participants) : 6125 ms Dense cycle check (100 participants) : 151797 ms
Backporting to 2.0.2 agreed by PMC
I have a matrix based implementation which does slightly better: Dense cycle check (5 participants) : 906 ms Dense cycle check (10 participants) : 2187 ms Dense cycle check (20 participants) : 5531 ms Dense cycle check (100 participants) : 132281 ms
Note that these numbers are not reflecting 1 cycle check detection, but rather <n> project classpath settings, when they all refer to each other. However this reflects closely what occurs during plugin imports (all project classpaths are occurring in the row).
With latest changes for batching JavaModelOperation (targeted for release in 2.1M2), the 100 projects update takes about 1.5 seconds. Had to change the test to use batching and move timer around classpath settings (to not include the time for creating project resources ~ 15 seconds on the 100 participants scenario). In summary, batching is good.
Actually, 1.5 seconds was too optimistic, we had a bug causing some work to no longer be completed ever (update project references). After fixing this, it takes 4.5 seconds for 100 projects scenario, which is still acceptable.