Community
Participate
Working Groups
Version: 2.0.1 Build id: 200211071448 Platform: Windows 2000 I have a tool that listens to resource change events on java classes. When a class changes, the tool needs to find the class' children (by "children" I mean both the classes that extend and those that implement). To find the children, the tool calls org.eclipse.jdt.core.IType::newTypeHierarchy(IJavaProject, IProgressMonitor); A performance problem was reported on a large workspace. Through a combination of log entries (elapsed time) and a profiling tool, I discovered that 94% of the tool's time is spent in newTypeHierarchy. We need a fix or workaround. Some stats on the log: Number of times newTypeHierarchy method is called: 12275 Average milliseconds per method invocation: 2417 Median milliseconds per method invocation: 0 Maximum milliseconds spent in method: 424188
We need steps to reproduce. Also, is it the same hierarchy over and over again ? If so, you can register as a listener to it, and get notified when it becomes stale.
Until it becomes stale, the hierarchy wouldn't need to be refreshed. see ITypeHierarchyChangedListener
The performance problem is intermittent and I don't have a small reproducible test case. Is there some logging mechanism that can be turned on, or something that can be added to the log that would provide you with the information that you need? According to the person who owns the workspace, almost every file in the workspace uses inheritance and all of them have a similiar family tree. They differ at the lowest level or second lowest level. Is there another method that should be called instead of newTypeHierarchy? Is there a way to get just a subtype hierarchy? Can a method be added, e.g., retrieveTypeHierarchy, that returns a subtype hierarchy (either a new hierarchy if the hierarchy doesn't exist or is stale, or the existing hierarchy if it exists and is not stale)? I am concerned about adding ITypeHierarchyChangedListeners because the tool is generic and I don't know how many hierarchies may exist. We need to reduce memory footprint and there's no way to know how many ITypeHierarchyChangedListeners would need to be created.
We don't cache type hierarchies. They are computed on the fly, and are notified when some portion of it could be affected by a relevant resource changes. Supertypes are almost free, subtypes need to be searched for, these are time consuming and account for the numbers you are seeing. Assuming you actually would care about one hierarchy, you could create one on the most specific common supertype, then you can navigate from there and find all others as subtypes. You would only need one listener to monitor this hierarchy changing. However, since I don't understand your scenario yet, I don't know if types in this hierarchy are actually affected by the resource change events (if so, then the hierarchy would rapidly think it is stale and become out of sync). Alternatively, you could consider using the SearchEngine to find items in a particular hierarchy. What is it exactly trying to achieve when looking for subtypes ? Particular methods, fields ?
Additionally, we could add a search query for finding direct subtypes of a particular type (type hierarchies are doing way more than that). See SearchEngine.createPattern, would a new type of query improve your situation ? Internally we can query direct supertype references, and we could surface these. Note that all additions could occur in 2.1 stream most likely.
Unfortunately, we need all subtypes, and all methods & fields of each subtype, so the SearchEngine won't help. I don't know how often the resource change affects the structure of the type hierarchy. I haven't collected those statistics from the tool's users. It sounds to me that the tool needs a cache of ITypeHierarchy instances, and for each ITypeHierarchy there needs to be an ITypeHierarchyChangeListener. It's a tradeoff between the memory footprint and the performance problem. I'll experiment with a cache and see if it resolves the situation. Many thanks for your help, Philippe!
A type hierarchy itself isn't big in memory, it is simply a collection of type handles. So caching them should be just fine. I had the impression you had only one big hierarchy but many viewpoints on it (different subtrees), so by computing the hierarchy of the most specific common supertype, you could hold onto one bigger hierarchy (slower to compute though, and more sensitive to invalidation) in case it simplified your job. Anyway, good luck and let us know how it goes.
After spending some time getting the cache working, I realized that the cache will fix the situation only some of the time. It is still possible for the customer's build to take eight hours if the cache is initially populated from the leaf nodes instead of the most specific common supertype. We need a solution that works all of the time. I realize that the problem is not easily reproducible. The customer builds around 20 to 30 times a day, and this performance problem occurs about once a day. I can change the tool to send data to the log; what information do you need? Incidentally, the customer found a workaround. Speaking from ignorance, maybe the workaround will suggest what area of the JDT to look at? "Another thing I wanted to bring up is that the current workaround that we've been using is to reimport the projects into the workspace each build cycle. This seems to be working on a longer term basis (we have to yet to see problems when this is implemented)."
We have tracing options (see our .options inside org.eclipse.jdt.core plugin folder) which you could enable to see what's going on. I would suggest first the following set: # Turn on debug tracing for org.eclipse.jdt.core plugin org.eclipse.jdt.core/debug=true # Report type hierarchy connections, refreshes and deltas org.eclipse.jdt.core/debug/hierarchy=true Is it possible to obtain the client workspace and steps to reproduce ? Also, is the workspace in autobuild mode ? Are the changes being built as they occur, if so you could consider using a post-Java builder and react to .class file changes to update a hierarchy graph (JDT/Core has some support to decode classfiles). Ideally, the source model is preferable to consider, but this could be a workaround.
Is it ok to close or do you need more from us ?
I'm waiting for the customer to respond to your previous instructions. I emailed them asking them to respond today; it is not okay to close this bugzilla yet. Thanks.
Ok, will keep it active then.
Is this still an issue ?
If more information is available, please reopen the problem for further consideration.
Closing since no activity in past 3 months.
As of now 'LATER' and 'REMIND' resolutions are no longer supported. Please reopen this bug if it is still valid for you.