Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 314551

Summary: [patch] Avoid creating children of IncludeReference when editor is closed
Product: [Tools] CDT Reporter: Ed Swartz <ed.swartz>
Component: cdt-editorAssignee: Anton Leherbauer <aleherb+eclipse>
Status: VERIFIED FIXED QA Contact: Anton Leherbauer <aleherb+eclipse>
Severity: normal    
Priority: P3 Keywords: performance
Version: 7.0   
Target Milestone: 7.0   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
patch
none
Implement IncludeReference.exists() aleherb+eclipse: iplog-

Description Ed Swartz CLA 2010-05-26 14:31:18 EDT
Created attachment 170068 [details]
patch

In our product, we deal with a lot of C/C++ files shared on a network (e.g. in a Windows share).  Generating the outline takes a long time, esp. due to the IncludeReference#computeChildren() call, which can end up investigating every file in a remote directory.

I looked and couldn't find a good solution for IncludeReference, so that's not addressed here.  

What's frustrating is, we've already turned off the Outline view and enabled scalability mode to avoid generating the Outline, but unfortunately, when we close the editor, the outline (model) is computed anyway!  So Eclipse is locked up for 10-20 seconds at a time.

This happens because CElement#exists() will check getElementInfo() != null -- but that call can result in fully generating the model, which seems like a silly thing to do right before you're closing something.  Note the stack trace.

This patch should address this issue, essentially by avoiding CElement#openWhenClosed() in a call to CElement#exists().  Only #open() or a myriad of getters or modification calls will invoke #openWhenClosed() now.

Is this a sensible workaround?  (It does work nicely for us and doesn't appear to impact normal behavior.)

Thread [main] (Suspended)	
	WinNTFileSystem.getBooleanAttributes(File) line: not available [native method]	
	File.isFile() line: 778	
	IncludeReference.computeChildren(OpenableInfo, IResource) line: 114	
	IncludeReference.buildStructure(OpenableInfo, IProgressMonitor, Map<ICElement,CElementInfo>, IResource) line: 82	
	IncludeReference(Openable).generateInfos(CElementInfo, Map<ICElement,CElementInfo>, IProgressMonitor) line: 265	
	IncludeReference(CElement).openWhenClosed(CElementInfo, IProgressMonitor) line: 430	
	IncludeReference(CElement).getElementInfo(IProgressMonitor) line: 309	
	IncludeReference(CElement).getElementInfo() line: 299	
	IncludeReference(CElement).exists() line: 138	
	DestroyWorkingCopyOperation.executeOperation() line: 40	
	DestroyWorkingCopyOperation(CModelOperation).execute() line: 338	
	DestroyWorkingCopyOperation(CModelOperation).run(IProgressMonitor) line: 603	
	DestroyWorkingCopyOperation(CModelOperation).runOperation(IProgressMonitor) line: 631	
	WorkingCopy.destroy() line: 133	
	CDocumentProvider.disposeFileInfo(Object, TextFileDocumentProvider$FileInfo) line: 930	
	CDocumentProvider(TextFileDocumentProvider).disconnect(Object) line: 653	
	CEditor(AbstractTextEditor).disposeDocumentProvider() line: 4349	
	CEditor(AbstractDecoratedTextEditor).disposeDocumentProvider() line: 1427	
	CEditor(AbstractTextEditor).dispose() line: 4236	
	CEditor(AbstractDecoratedTextEditor).dispose() line: 368	
	CEditor(TextEditor).dispose() line: 93	
	CEditor.dispose() line: 2090
Comment 1 Anton Leherbauer CLA 2010-05-27 08:39:15 EDT
Calling getElementInfo() with a canceled progress monitor is a nasty hack.
I think implementing IncludeReference.exists() would be a better solution.
Comment 2 Anton Leherbauer CLA 2010-05-27 08:50:19 EDT
BTW, the stack trace does not indicate that any parsing is done.  The performance problem is caused by traversing the file system for the include files of a IncludeReference container.  The IncludeReference element is not part of the Outline view.
Comment 3 Ed Swartz CLA 2010-05-27 09:07:48 EDT
Thanks for the review, and sorry I misanalyzed the issue.  

I agree the hack was nasty.  :)  I went down this route to demonstrate the minimal changes that would work for us.  

Note also that it would be nice if the progress monitor support could be hooked up (it gets lost between CModelOperation#execute and CElement#getElementInfo).  When bringing up a quick outline, rather than closing the editor, I can get into the same code path and cannot cancel the operation.  The UI freezes until all the thousands of files have been scanned.
Comment 4 Anton Leherbauer CLA 2010-05-27 09:24:26 EDT
(In reply to comment #3)
> Thanks for the review, and sorry I misanalyzed the issue.  

I updated the summary accordingly.

> Note also that it would be nice if the progress monitor support could be hooked
> up (it gets lost between CModelOperation#execute and CElement#getElementInfo). 

This would need an API change, because not all methods accessing getElementInfo() take a progress monitor.

> When bringing up a quick outline, rather than closing the editor, I can get
> into the same code path and cannot cancel the operation.  The UI freezes until
> all the thousands of files have been scanned.

This should also be fixed when IncludeReference overrides exists().
Comment 5 Anton Leherbauer CLA 2010-05-28 04:43:29 EDT
Created attachment 170311 [details]
Implement IncludeReference.exists()

This should address the performance issue.
Comment 6 Anton Leherbauer CLA 2010-05-28 06:10:39 EDT
Committed to HEAD.
Comment 7 Ed Swartz CLA 2010-05-28 08:33:33 EDT
Thanks, this works nicely!
Comment 8 CDT Genie CLA 2010-05-28 09:18:33 EDT
*** cdt cvs genie on behalf of aleherbau ***
Bug 314551 - [patch] Avoid creating children of IncludeReference when editor is closed

[*] IncludeReference.java 1.23 http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.cdt-core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IncludeReference.java?root=Tools_Project&r1=1.22&r2=1.23