Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 328818 - UI freeze during expanding EJB project
Summary: UI freeze during expanding EJB project
Status: RESOLVED FIXED
Alias: None
Product: WTP Java EE Tools
Classification: WebTools
Component: jst.j2ee (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 3.3.2   Edit
Assignee: Dimitar Giormov CLA
QA Contact: Chuck Bridgham CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 329966 352841
  Show dependency tree
 
Reported: 2010-10-27 08:50 EDT by Krzysztof Daniel CLA
Modified: 2011-11-08 03:42 EST (History)
4 users (show)

See Also:
cbridgha: review+


Attachments
Dirty, ugly hack which works only for one project and has a lot of errors (10.24 KB, patch)
2010-10-27 11:09 EDT, Krzysztof Daniel CLA
no flags Details | Diff
Much better patch (16.46 KB, patch)
2010-10-28 08:52 EDT, Krzysztof Daniel CLA
dimitar.giormov: iplog+
Details | Diff
Loading models will happen outside of UI Thread. (13.49 KB, patch)
2011-07-21 16:39 EDT, Dimitar Giormov CLA
no flags Details | Diff
same patch just removed some not needed method that might cause NPE (22.33 KB, patch)
2011-08-09 08:32 EDT, Dimitar Giormov CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Krzysztof Daniel CLA 2010-10-27 08:50:16 EDT
It is known that parsing Java EE annotation model (bug 198815 c 12) may take a long time. Actually it may take as much as 5 minutes for a medium project with about 60 beans. 
The model is parsed when the project is expanded in the Project Explorer, which causes 5 minutes adopter product freeze.

 org.eclipse.jst.jee.ui.internal.navigator.Ejb3ContentProvider.getChildren(Ejb3ContentProvider.java:75) should adopt lazy approach as described in the post http://dev.eclipse.org/newslists/news.eclipse.platform/msg55021.html to avoid UI freeze.
Comment 1 Carl Anderson CLA 2010-10-27 09:45:55 EDT
Assigning to Kaloyan for initial investigation - SAP contributed the Ejb3ContentProvider code.

Christopher, to clarify, which version of WTP are you reporting this against?
Comment 2 Krzysztof Daniel CLA 2010-10-27 09:50:46 EDT
I have reproduced this with 3.7M2a, but it is a problem in 3.6, too.
Comment 3 Carl Anderson CLA 2010-10-27 10:23:23 EDT
Eclipse 3.6 corresponds to WTP 3.2, so I am setting the version to 3.2.
Comment 4 Krzysztof Daniel CLA 2010-10-27 11:09:06 EDT
Created attachment 181845 [details]
Dirty, ugly hack which works only for one project and has a lot of errors

Some initial work. Further advice is welcome.
Comment 5 Kaloyan Raev CLA 2010-10-27 15:57:20 EDT
Christopher, thank you for the comprehensive bug report. 

Dimitar, you are more familiar with the EJB 3 model than me. Could you take care?
Comment 6 Krzysztof Daniel CLA 2010-10-28 08:52:31 EDT
Created attachment 181931 [details]
Much better patch

It works. Only the actions "New bean" throw exception, but UI is no longer blocked.
Comment 7 Dimitar Giormov CLA 2010-10-28 09:05:19 EDT
Thanks Christopher, 

What I can do about this is to proceed in the same manner as in J2ee 1.4
models, where an animation shows that the model is being loaded and the tree is
expanded afterwords. 

But trying to simulate the same scenario on my pc having 100 beans (80 session,
20 MDb's) does not brought performance degradation. The tree opens like always
(under a second) I tried and brought some more annotations and EJB injections,
but it kept working ok. It could be that some referenced projects or network
latency can cause this. 
(how I tested is trying to open the project and DD tree node right after the
eclipse is started, so nothing is cached)

Can you share some project(s) that has this performance degradation, it could
be that a certain property takes a lot of time to be processed.

To summarize :)
I will make the loading of the model asynchronous. I will start with your new patch.
I need your help to figure out where these long running operations occur.

P.S. attach binary files such as images separately. Having them in a patch makes them useless.
Comment 8 Krzysztof Daniel CLA 2010-10-28 09:27:35 EDT
Unfortunately I cannot share the project - I will try to build a minimal test case.

Here is javacore:

String.lastIndexOf(int, int) line: 856	
String.lastIndexOf(int) line: 835	
NameLookup.seekTypesInSourcePackage(String, IPackageFragment, int, boolean, String, int, IJavaElementRequestor) line: 1078	
NameLookup.seekTypes(String, IPackageFragment, boolean, int, IJavaElementRequestor) line: 987	
NameLookup.findType(String, IPackageFragment, boolean, int) line: 776	
NameLookup.findType(String, String, boolean, int, boolean, boolean, boolean, IProgressMonitor) line: 660	
NameLookup.findType(String, String, boolean, int, boolean) line: 619	
SearchableEnvironment.find(String, String) line: 101	
SearchableEnvironment.findType(char[], char[][]) line: 287	
LookupEnvironment.askForType(PackageBinding, char[]) line: 132	
PackageBinding.getTypeOrPackage(char[]) line: 183	
ClassScope(Scope).getTypeOrPackage(char[], int, boolean) line: 2642	
ClassScope(Scope).getType(char[]) line: 2359	
SingleTypeReference.getTypeBinding(Scope) line: 44	
SingleTypeReference(TypeReference).internalResolveType(Scope) line: 131	
SingleTypeReference(TypeReference).resolveType(ClassScope) line: 207	
SingleTypeReference(TypeReference).resolveTypeArgument(ClassScope, ReferenceBinding, int) line: 225	
ParameterizedQualifiedTypeReference.internalResolveType(Scope, boolean) line: 213	
ParameterizedQualifiedTypeReference.resolveType(ClassScope) line: 341	
ParameterizedQualifiedTypeReference(TypeReference).resolveSuperType(ClassScope) line: 185	
ClassScope.findSupertype(TypeReference) line: 1213	
ClassScope.connectSuperInterfaces() line: 980	
ClassScope.connectTypeHierarchy() line: 1034	
CompilationUnitScope.connectTypeHierarchy() line: 299	
LookupEnvironment.completeTypeBindings(CompilationUnitDeclaration, boolean) line: 258	
SelectionEngine(Engine).accept(ISourceType[], PackageBinding, AccessRestriction) line: 99	
LookupEnvironment.askForType(PackageBinding, char[]) line: 144	
PackageBinding.getTypeOrPackage(char[]) line: 183	
ClassScope(Scope).getTypeOrPackage(char[], int, boolean) line: 2642	
ClassScope(Scope).getType(char[]) line: 2359	
SingleTypeReference.getTypeBinding(Scope) line: 44	
SingleTypeReference(TypeReference).internalResolveType(Scope) line: 131	
SingleTypeReference(TypeReference).resolveType(ClassScope) line: 207	
SingleTypeReference(TypeReference).resolveTypeArgument(ClassScope, ReferenceBinding, int) line: 225	
ParameterizedQualifiedTypeReference.internalResolveType(Scope, boolean) line: 213	
ParameterizedQualifiedTypeReference.resolveType(ClassScope) line: 341	
ParameterizedQualifiedTypeReference(TypeReference).resolveSuperType(ClassScope) line: 185	
ClassScope.findSupertype(TypeReference) line: 1213	
ClassScope.connectSuperInterfaces() line: 980	
ClassScope.connectTypeHierarchy() line: 1034	
CompilationUnitScope.connectTypeHierarchy() line: 299	
LookupEnvironment.completeTypeBindings(CompilationUnitDeclaration, boolean) line: 258	
SelectionEngine(Engine).accept(ISourceType[], PackageBinding, AccessRestriction) line: 99	
LookupEnvironment.askForType(PackageBinding, char[]) line: 144	
PackageBinding.getTypeOrPackage(char[]) line: 183	
ClassScope(Scope).getTypeOrPackage(char[], int, boolean) line: 2642	
ClassScope(Scope).getType(char[]) line: 2359	
SingleTypeReference.getTypeBinding(Scope) line: 44	
SingleTypeReference(TypeReference).internalResolveType(Scope) line: 131	
SingleTypeReference(TypeReference).resolveType(ClassScope) line: 207	
SingleTypeReference(TypeReference).resolveTypeArgument(ClassScope, ReferenceBinding, int) line: 225	
ParameterizedQualifiedTypeReference.internalResolveType(Scope, boolean) line: 213	
ParameterizedQualifiedTypeReference.resolveType(ClassScope) line: 341	
ParameterizedQualifiedTypeReference(TypeReference).resolveSuperType(ClassScope) line: 185	
ClassScope.findSupertype(TypeReference) line: 1213	
ClassScope.connectSuperInterfaces() line: 980	
ClassScope.connectTypeHierarchy() line: 1034	
CompilationUnitScope.connectTypeHierarchy() line: 299	
LookupEnvironment.completeTypeBindings(CompilationUnitDeclaration, boolean) line: 258	
SelectionEngine(Engine).accept(ISourceType[], PackageBinding, AccessRestriction) line: 99	
LookupEnvironment.askForType(PackageBinding, char[]) line: 144	
PackageBinding.getTypeOrPackage(char[]) line: 183	
ClassScope(Scope).getTypeOrPackage(char[], int, boolean) line: 2642	
ClassScope(Scope).getType(char[]) line: 2359	
SingleTypeReference.getTypeBinding(Scope) line: 44	
SingleTypeReference(TypeReference).internalResolveType(Scope) line: 131	
SingleTypeReference(TypeReference).resolveType(ClassScope) line: 207	
SingleTypeReference(TypeReference).resolveTypeArgument(ClassScope, ReferenceBinding, int) line: 225	
ParameterizedQualifiedTypeReference.internalResolveType(Scope, boolean) line: 213	
ParameterizedQualifiedTypeReference.resolveType(ClassScope) line: 341	
ParameterizedQualifiedTypeReference(TypeReference).resolveSuperType(ClassScope) line: 185	
ClassScope.findSupertype(TypeReference) line: 1213	
ClassScope.connectSuperInterfaces() line: 980	
ClassScope.connectTypeHierarchy() line: 1034	
CompilationUnitScope.connectTypeHierarchy() line: 299	
LookupEnvironment.completeTypeBindings(CompilationUnitDeclaration, boolean) line: 258	
SelectionEngine(Engine).accept(ISourceType[], PackageBinding, AccessRestriction) line: 99	
LookupEnvironment.askForType(PackageBinding, char[]) line: 144	
PackageBinding.getTypeOrPackage(char[]) line: 183	
ClassScope(Scope).getTypeOrPackage(char[], int, boolean) line: 2642	
ClassScope(Scope).getType(char[]) line: 2359	
SingleTypeReference.getTypeBinding(Scope) line: 44	
SingleTypeReference(TypeReference).internalResolveType(Scope) line: 131	
SingleTypeReference(TypeReference).resolveType(ClassScope) line: 207	
SingleTypeReference(TypeReference).resolveTypeArgument(ClassScope, ReferenceBinding, int) line: 225	
ParameterizedQualifiedTypeReference.internalResolveType(Scope, boolean) line: 213	
ParameterizedQualifiedTypeReference.resolveType(ClassScope) line: 341	
ParameterizedQualifiedTypeReference(TypeReference).resolveSuperType(ClassScope) line: 185	
ClassScope.findSupertype(TypeReference) line: 1213	
ClassScope.connectSuperInterfaces() line: 980	
ClassScope.connectTypeHierarchy() line: 1034	
CompilationUnitScope.connectTypeHierarchy() line: 299	
LookupEnvironment.completeTypeBindings(CompilationUnitDeclaration, boolean) line: 258	
SelectionEngine(Engine).accept(ISourceType[], PackageBinding, AccessRestriction) line: 99	
LookupEnvironment.askForType(PackageBinding, char[]) line: 144	
PackageBinding.getTypeOrPackage(char[]) line: 183	
CompilationUnitScope.findImport(char[][], int) line: 486	
CompilationUnitScope.findSingleImport(char[][], int, boolean) line: 540	
CompilationUnitScope.faultInImports() line: 368	
CompilationUnitScope.faultInTypes() line: 465	
SelectionEngine.selectType(char[], IType) line: 1425	
SourceType(NamedMember).resolveType(String, WorkingCopyOwner) line: 292	
SourceType(NamedMember).resolveType(String) line: 245	
EjbAnnotationFactory.processImplementedInterfaces(SessionBean, IType, Collection<IType>, IProgressMonitor) line: 331	
EjbAnnotationFactory.createSession(Result, SessionType, IAnnotation, IType) line: 201	
EjbAnnotationFactory.processStatelessBean(Result, IAnnotation, IType) line: 141	
EjbAnnotationFactory.createJavaeeObject(IType) line: 119	
EJBAnnotationReader.analyzeUnitForBean(ICompilationUnit) line: 290	
EJBAnnotationReader.loadModel() line: 225	
EJBAnnotationReader(AbstractAnnotationModelProvider<T>).getConcreteModel() line: 106	
EJBAnnotationReader(AbstractAnnotationModelProvider<T>).getModelObject() line: 122	
EJB3MergedModelProvider(AbstractMergedModelProvider<T>).loadProviders() line: 242	
AbstractMergedModelProvider<T>.access$1(AbstractMergedModelProvider) line: 235	
AbstractMergedModelProvider$LoadModelsWorkspaceRunnable.run(IProgressMonitor) line: 255	
Workspace.run(IWorkspaceRunnable, ISchedulingRule, int, IProgressMonitor) line: 1975	
EJB3MergedModelProvider(AbstractMergedModelProvider<T>).loadModel() line: 229	
EJB3MergedModelProvider(AbstractMergedModelProvider<T>).getMergedModel() line: 213	
EJB3MergedModelProvider(AbstractMergedModelProvider<T>).getModelObject() line: 133	
Ejb3ContentProvider$LoadContentProviderJob.run(IProgressMonitor) line: 275	
Worker.run() line: 54
Comment 9 Krzysztof Daniel CLA 2010-10-28 09:46:52 EDT
Alternative approach maybe to dump annotations model to file, so EJBAnnotationReader#loadModel could load it from file, and then, in the background, process diffs, if any.
Comment 10 Dimitar Giormov CLA 2010-10-28 10:09:03 EDT
The most expensive operations should be the building of the annotation model itself. All operation afterwords are trivial. From your stacktrace it currently resolves a type. Which is one of the expensive operations we do.
Can you try to profile the operation. 
this article can help you how if you haven't done it till now:
http://www.eclipse.org/articles/Article-TPTP-Profiling-Tool/tptpProfilingArticle.html
Comment 11 Dimitar Giormov CLA 2010-11-08 09:16:43 EST
Christopher the 3.2.3 release draws near, if you can provide some junit or profile results, on which I can work on it will be great.
The impact of such performance degradation could be huge. We can easily fix the tree, but wizards for creating an artifact calls these same methods for the purpose of validation on every keystroke for example.
Comment 12 Krzysztof Daniel CLA 2010-11-08 10:42:57 EST
I am sorry, my priorities has been shifted and I am no longer able to work on this issue. 

The problem was visible only during the first model loading after restart, so you should not be worried about validators (I also bet that there is some kind of caching during type resolution).

It looks like the number of beans is not the only factor - those beans had also very high stack of inheritance.
Comment 13 Dimitar Giormov CLA 2010-11-09 05:58:10 EST
OK shifting it to indigo.
Where the async loading will occur.
Comment 14 Dimitar Giormov CLA 2011-05-20 02:58:02 EDT
re-targeting for SR1
Comment 15 Dimitar Giormov CLA 2011-07-21 16:39:58 EDT
Created attachment 200122 [details]
Loading models will happen outside of UI Thread.

Christopher, I took your patch and change it a bit, I took advantage of some already written code, that is used for the same purpose for J2EE models (ver. 1.4)

I also make it generic for all project types.

I have added some fixes for Application Client DD Node, since there were some triggers missing.
It won't still refresh correctly on first add, but I will address it in another bug.

@Chuck can you review the patch?
Comment 16 Dimitar Giormov CLA 2011-07-22 05:53:05 EDT
separate bug for App Client created: https://bugs.eclipse.org/bugs/show_bug.cgi?id=352841
Comment 17 Chuck Bridgham CLA 2011-08-04 17:16:12 EDT
looks ok - thanks
Comment 18 Dimitar Giormov CLA 2011-08-09 08:32:29 EDT
Created attachment 201135 [details]
same patch just removed some not needed method that might cause NPE

reviewing the code before committing just noticed that the methods hasChildren can cause potential NPE 
since some of them call getChildren().isEmpty() and getChildren can return null. Also noticed that there is already much safer hasChildren method in the parent class.
Comment 19 Dimitar Giormov CLA 2011-08-09 08:38:01 EDT
@Chuck I am not sure if I have to set it for review again?

the difference into the patches is that the hasChildren method is deleted so the one in AbstractGroupProvider is user, which has safer implementation. With this patch I set javaee variable to null so it possible that NPE will appear without this fix.
Comment 20 Chuck Bridgham CLA 2011-08-24 22:13:05 EDT
still looks good thanks
Comment 21 Dimitar Giormov CLA 2011-09-13 02:31:54 EDT
targeting for SR2
Comment 22 Dimitar Giormov CLA 2011-11-07 05:03:02 EST
Committed and release in HEAD and 3_3_Maintenance
Comment 23 Carl Anderson CLA 2011-11-07 14:04:35 EST
Dimitar, was this critical for WTP 3.4.0 M3 shutdown?  I fixed the versioning problem that this caused (since those prevent us from declaring).  We needed to rebuild because of the DTP prereq change... but a change like this probably should have waited until after the M3 declare.
Comment 24 Dimitar Giormov CLA 2011-11-08 03:42:23 EST
Sorry about that. I waited Friday releases to pass, but I have missed that M3 was not declared.