Bug 440470 - debugger source lookup is much slower than 4.3
Summary: debugger source lookup is much slower than 4.3
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.4   Edit
Hardware: All All
: P3 normal with 6 votes (vote)
Target Milestone: 3.6.2+J7   Edit
Assignee: Markus Keller CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
: 439450 440517 443590 524659 (view as bug list)
Depends on: 410207
Blocks:
  Show dependency tree
 
Reported: 2014-07-25 22:55 EDT by Lee Breisacher CLA
Modified: 2019-12-18 02:02 EST (History)
19 users (show)

See Also:
daniel_megert: pmc_approved+
stephan.herrmann: review+


Attachments
Fix (3.27 KB, patch)
2014-08-29 10:48 EDT, Markus Keller CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Lee Breisacher CLA 2014-07-25 22:55:37 EDT
I have a project with a rather long classpath, more than 400 entries. When the debugger first stops at a breakpoint, it takes more than 30 seconds before it shows the source. I used visualvm to capture some thread dumps during that 30 seconds, and most of them look like this:

"Worker-54" #503 prio=5 os_prio=0 tid=0x000000001a794800 nid=0x41ce4 runnable [0x00000000327de000]
   java.lang.Thread.State: RUNNABLE
	at java.io.WinNTFileSystem.getLastModifiedTime(Native Method)
	at java.io.File.lastModified(Unknown Source)
	at java.util.zip.ZipFile.<init>(Unknown Source)
	at java.util.zip.ZipFile.<init>(Unknown Source)
	at java.util.zip.ZipFile.<init>(Unknown Source)
	at org.eclipse.jdt.internal.core.JavaModelManager.getZipFile(JavaModelManager.java:2712)
	at org.eclipse.jdt.internal.core.util.Util.getJdkLevel(Util.java:846)
	at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.<init>(JarPackageFragmentRoot.java:76)
	at org.eclipse.jdt.internal.core.JavaProject.getPackageFragmentRoot(JavaProject.java:1810)
	at org.eclipse.jdt.internal.core.JavaProject.computePackageFragmentRoots(JavaProject.java:615)
	at org.eclipse.jdt.internal.core.JavaProject.computePackageFragmentRoots(JavaProject.java:708)
	at org.eclipse.jdt.internal.core.JavaProject.computePackageFragmentRoots(JavaProject.java:672)
	at org.eclipse.jdt.internal.core.JavaProject.getAllPackageFragmentRoots(JavaProject.java:1430)
	at org.eclipse.jdt.internal.core.JavaProject.getAllPackageFragmentRoots(JavaProject.java:1425)
	at org.eclipse.jdt.internal.core.JavaProject.findPackageFragmentRoot0(JavaProject.java:1228)
	at org.eclipse.jdt.internal.core.JavaProject.findPackageFragmentRoot(JavaProject.java:1220)
	at org.eclipse.jdt.internal.launching.JavaSourceLookupUtil.getPackageFragmentRoot(JavaSourceLookupUtil.java:157)
	at org.eclipse.jdt.internal.launching.JavaSourceLookupUtil.translate(JavaSourceLookupUtil.java:57)
	at org.eclipse.jdt.launching.JavaRuntime.getSourceContainers(JavaRuntime.java:2449)
	at org.eclipse.jdt.launching.sourcelookup.containers.JavaSourcePathComputer.computeSourceContainers(JavaSourcePathComputer.java:58)
	at org.eclipse.debug.internal.core.sourcelookup.SourcePathComputer.computeSourceContainers(SourcePathComputer.java:71)
	at org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer.createSourceContainers(DefaultSourceContainer.java:117)
	at org.eclipse.debug.core.sourcelookup.containers.CompositeSourceContainer.getSourceContainers(CompositeSourceContainer.java:133)
	- locked <0x00000000fa6ee7a8> (a org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer)
	at org.eclipse.debug.core.sourcelookup.containers.CompositeSourceContainer.findSourceElements(CompositeSourceContainer.java:48)
	at org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant.findSourceElements(AbstractSourceLookupParticipant.java:70)
	at org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector$SourceLookupQuery.run(AbstractSourceLookupDirector.java:142)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector.doSourceLookup(AbstractSourceLookupDirector.java:505)
	at org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector.getSourceElement(AbstractSourceLookupDirector.java:785)
	at org.eclipse.debug.internal.ui.sourcelookup.SourceLookupFacility.lookup(SourceLookupFacility.java:346)
	- locked <0x00000000ae4fd858> (a org.eclipse.debug.internal.ui.sourcelookup.SourceLookupFacility$LRU)
	at org.eclipse.debug.internal.ui.sourcelookup.SourceLookupFacility$SourceLookupJob.run(SourceLookupFacility.java:737)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)

When I do the exact same thing with the exact same project in eclipse 4.3.x, the source lookup takes just a second or so - very fast. 

I suspect the problem is in the JarPackageFragmentRoot constructor where it is calling Util.getJdkLevel -- it looks like older versions of JarPackageFragmentRoot didn't have that, but I'm just speculating -- I don't really know that much about it.
Comment 1 Gary Gregory CLA 2014-07-26 00:11:46 EDT
I am experiencing the same problem.
Comment 2 Sarika Sinha CLA 2014-07-28 05:26:49 EDT
*** Bug 440517 has been marked as a duplicate of this bug. ***
Comment 3 Sarika Sinha CLA 2014-07-30 05:34:38 EDT
looks like same as bug 439450

Lee, can you confirm if debugger is fast in projects without libs ?
Comment 4 Daniel Migowski CLA 2014-07-30 08:42:00 EDT
I wonder why there has to be a zip file lookup in the first place. I believed the jar files would have been indexed anyway long before one starts to debug the code, so why would one want to do a lookup into the jar files now? Even if the source can be found in the source folders of the project and they are at the top of the build path...
Comment 5 Lee Breisacher CLA 2014-07-30 09:03:12 EDT
Oh yeah, sorry I meant to say that, Yes indeed the debugger is fast on a project without libs. 

(In reply to Sarika Sinha from comment #3)
> looks like same as bug 439450
> 
> Lee, can you confirm if debugger is fast in projects without libs ?
Comment 6 Sarika Sinha CLA 2014-07-30 23:51:50 EDT
*** Bug 439450 has been marked as a duplicate of this bug. ***
Comment 7 NSV CLA 2014-08-05 14:57:16 EDT
I have the exact same problem on Centos 6.

On big project the debug is very slow.
On "normal" project the debug is very quick
Comment 8 t h CLA 2014-08-27 04:25:46 EDT
No problem with 4.3, with 4.4 the debugger is extreme slow.
Comment 9 Michael Rennie CLA 2014-08-28 11:00:25 EDT
(In reply to t h from comment #8)
> No problem with 4.3, with 4.4 the debugger is extreme slow.

I wonder too, if bug 437193 was causing some of this slow-down. As part of the fix for that bug we got rid of one entire layer of (UI)Jobs.
Comment 10 Dani Megert CLA 2014-08-29 09:54:28 EDT
(In reply to Michael Rennie from comment #9)
> (In reply to t h from comment #8)
> > No problem with 4.3, with 4.4 the debugger is extreme slow.
> 
> I wonder too, if bug 437193 was causing some of this slow-down. As part of
> the fix for that bug we got rid of one entire layer of (UI)Jobs.

If so, we have to fix this in 4.4.x too.
Comment 11 Markus Keller CLA 2014-08-29 10:18:17 EDT
I'm pretty sure the regression is due to the fix for bug 410207. Moving to JDT Core.

Like every IJavaElement, JarPackageFragmentRoot is supposed to be a *handle*, i.e. it should be very lightweight and its creation should not depend on availability of the referenced element.

The JarPackageFragmentRoot#complianceLevel field is unnecessary. This value should be computed in #computeChildren(..). I'm preparing a patch.
Comment 12 Stephan Herrmann CLA 2014-08-29 10:35:15 EDT
Is this the same performance regression that has been fixed via bug 441726?
Comment 13 Markus Keller CLA 2014-08-29 10:48:36 EDT
Created attachment 246547 [details]
Fix

Looks like there's already a workaround for this regression in master, see bug 441726. I think the solution chosen in that bug is wrong. Having to maintain yet another cache is unnecessary and fragile.

Here's a straightforward fix that just moves the computation of the complianceLevel back to where it should be.

This patch needs to be tested with the scenarios of this bug, bug 410207, bug 441726, and their dups.
After that, it needs to be backported to all branches that received bug 410207.
Comment 14 Dani Megert CLA 2014-08-29 10:51:33 EDT
+1 to fix this in 4.4.1 and below.
Comment 15 Stephan Herrmann CLA 2014-08-29 11:17:42 EDT
I'm sorry the regression occurred in the first place,
but how can moving initialization to a slightly later point help scenarios
like refreshing the package explorer (bug 441726 comment 0)?
Comment 16 Szymon Ptaszkiewicz CLA 2014-08-29 11:26:42 EDT
If the regression is caused by the bad fix for bug 410207, then it is my fault, sorry.
Comment 17 Markus Keller CLA 2014-08-29 11:39:25 EDT
(In reply to Stephan Herrmann from comment #15)
> but how can moving initialization to a slightly later point help scenarios
> like refreshing the package explorer (bug 441726 comment 0)?

It's all about the expected cost of operations:

The expected cost of a handle creation is negligible. That's why we can create new JarPackageFragmentRoot objects all the time.

On the other hand, we only call JarPackageFragmentRoot#computeChildren(..) when we're ready to pay the price for opening the JAR and reading its contents. The implementation of computeChildren(..) opens the ZipFile anyway (via getJar()), so the detection of the class file level is almost free there. The ZipFile is cached by the JavaModelManager.

If everything works as it should, then the children of a JarPackageFragmentRoot should be cached in a JavaElementInfo (here: JavaProjectElementInfo) and should only be re-computed when the Jar has been touched or when the element info cache overflows.
Comment 18 Markus Keller CLA 2014-08-29 13:35:56 EDT
I've verified that comment 13 fixes bug 441726. It brings that performance test back to 4.3.2 level, and it's a bit better than what's in master.
Comment 19 Stephan Herrmann CLA 2014-08-29 13:56:56 EDT
(In reply to Markus Keller from comment #17)

Thanks for explaining!
Comment 20 Terry Parker CLA 2014-08-29 17:29:46 EDT
(In reply to Markus Keller from comment #18)
> I've verified that comment 13 fixes bug 441726. It brings that performance
> test back to 4.3.2 level, and it's a bit better than what's in master.

I verified that as well. Somehow when evaluating bug 441726, I convinced myself that object/handle creation and JarPackageFragmentRoot#computeChildren() invocations were on the order of 1:1. Before reading your explanation I reinvestigated and saw I was mistaken. I support rolling back that change and implementing this one.

I also agree that having to maintain yet another cache is not good. My team has submitted several patches that fixed JDT caching problems, and we continue to find areas where caches are incorrectly evicted or underutilized. There appear to be too many caches, they are uncoordinated, and they are difficult to discover. I opened bug 442924, "Rationalize jar-related caches", where we can discuss the issue and try to make some progress.
Comment 21 Markus Keller CLA 2014-08-31 19:36:17 EDT
Thanks for the confirmation, Terry. I agree the current caching strategies are not as clear as they could/should be. Re "who's to blame": I think pretty much everybody involved can take a share, yours truly included.

I've verified that comment 13 still fixes bug 410207 as well.

I've reverted bug 441726 and committed comment 13 in master: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=d35306cb5dcf7e4ac666fd0505f3086f50241fb2
Comment 22 Gary Gregory CLA 2014-08-31 22:39:48 EDT
Will this make it in time for 4.4.1?
Comment 23 Markus Keller CLA 2014-09-01 06:42:09 EDT
(In reply to Gary D. Gregory from comment #22)
> Will this make it in time for 4.4.1?

Yes. N20140831-2000 already contains the fix. I'm running on that build now, and others could test it too (or test tomorrow's I-build).

Jay, please review the fix for R4_4_maintenance and the other branches where bug 410207 was released.
Comment 24 Jay Arthanareeswaran CLA 2014-09-01 08:42:10 EDT
Srikanth/Stephan, can you please review this for 4.4.1? I don't expect to be able to get to this today. TIA!
Comment 25 Stephan Herrmann CLA 2014-09-01 18:44:15 EDT
From looking at the code and reading comments here, I can confirm that http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=d35306cb5dcf7e4ac666fd0505f3086f50241fb2 is a very straight-forward and clean improvement on top of bug 410207.

I also checked that the sibling changes in PackageFragmentRoot and PackageFragmentRootInfo already perform their work during computeFolderChildren and computeFolderNonJavaResources, resp., good.

I did not dive into details of why bug 441726 would be inferior, except for aspect of clarity of design.

I also did not perform any performance measurements, trusting that comment 18 and comment 20 already sufficiently back this aspect.

Under these reservations I'm in favor of back porting to 4.4.1 and below.


BTW: I'm right now looking at poor performance of an Xtext-based tool, which is caused by this exact performance bug. As soon as we have a Luna-based build with this patch I can give it some real-world testing in that context.
Comment 26 Jay Arthanareeswaran CLA 2014-09-02 00:50:25 EDT
(In reply to Stephan Herrmann from comment #25)
> From looking at the code and reading comments here, I can confirm that
> http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/
> ?id=d35306cb5dcf7e4ac666fd0505f3086f50241fb2 is a very straight-forward and
> clean improvement on top of bug 410207.

Thanks Stephan. I will release this for 4.4.1 in a bit.
Comment 27 Jay Arthanareeswaran CLA 2014-09-02 04:36:49 EDT
(In reply to Jayaprakash Arthanareeswaran from comment #26)
> Thanks Stephan. I will release this for 4.4.1 in a bit.

It's here: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=R4_4_maintenance&id=5781fc0d3b262a5bc6ee6e12f16976ad6642c6ae

Stephan, for the records, can you please grant the +1 for the review.
Comment 28 Jay Arthanareeswaran CLA 2014-09-02 04:51:56 EDT
Resolving
Comment 29 Markus Keller CLA 2014-09-02 07:36:48 EDT
(In reply to Markus Keller from comment #13)
> it needs to be backported to all branches that received bug 410207.
Comment 30 Stephan Herrmann CLA 2014-09-02 09:07:54 EDT
(In reply to Jayaprakash Arthanareeswaran from comment #27)
> Stephan, for the records, can you please grant the +1 for the review.

sure
Comment 31 Stephan Herrmann CLA 2014-09-02 18:53:21 EDT
(In reply to Stephan Herrmann from comment #25)
> BTW: I'm right now looking at poor performance of an Xtext-based tool, which
> is caused by this exact performance bug. As soon as we have a Luna-based
> build with this patch I can give it some real-world testing in that context.

Quick test in the context of that Xtext-based tool:
Using build M20140902-1430 a full build for one particular project went down from 6 min to 2 min. Great!
Comment 32 Claudio Bottai CLA 2014-09-21 17:47:43 EDT
Siete penosi
Comment 35 Jay Arthanareeswaran CLA 2014-09-23 05:02:33 EDT
As per comment #31, marking as verified.
Comment 36 Jay Arthanareeswaran CLA 2014-09-24 07:53:20 EDT
*** Bug 443590 has been marked as a duplicate of this bug. ***
Comment 37 Michael Rennie CLA 2014-10-03 09:53:29 EDT
*** Bug 365394 has been marked as a duplicate of this bug. ***
Comment 38 Sarika Sinha CLA 2019-12-18 02:02:25 EST
*** Bug 524659 has been marked as a duplicate of this bug. ***