Bug 177384 - Provide API to determine max severity of markers under a given resource
Summary: Provide API to determine max severity of markers under a given resource
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Resources (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 3.3 M6   Edit
Assignee: John Arthorne CLA
QA Contact:
URL:
Whiteboard:
Keywords: api, performance
Depends on:
Blocks: 177390 177392 177393
  Show dependency tree
 
Reported: 2007-03-14 13:42 EDT by Nick Edgar CLA
Modified: 2007-03-21 10:23 EDT (History)
7 users (show)

See Also:


Attachments
Patch providing findMaxSeverity API (8.40 KB, patch)
2007-03-14 13:47 EDT, Nick Edgar CLA
no flags Details | Diff
Patch with additional optimization (1.02 KB, patch)
2007-03-15 11:57 EDT, John Arthorne CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Nick Edgar CLA 2007-03-14 13:42:53 EDT
3.3 M5

While looking into performance of our decorator, I noticed lots of overhead in computing the problem decorations in JDT, due to its use of IResource.findMarkers to determine the max problem severity.  

For example, one of our projects has 457 warnings.  In order to determine that a warning decoration is needed for the project, 457 Marker objects get created.

This could be reduced by providing a more specialized API that determines the max severity across markers on a resource.
Comment 1 Nick Edgar CLA 2007-03-14 13:47:52 EDT
Created attachment 60832 [details]
Patch providing findMaxSeverity API
Comment 2 Nick Edgar CLA 2007-03-14 13:58:52 EDT
Opened bug 177390 for the change to JDT to use this.
PDE may want to use it too for the error check before launch.
Comment 3 Wassim Melhem CLA 2007-03-14 14:01:56 EDT
This would certainly be useful.

The check for compiler errors before launching is done at the platform/debug level.  PDE gets it for free.  cc DarinW.
Comment 4 Nick Edgar CLA 2007-03-14 14:03:33 EDT
Here are some stats on the improvement:

decorating ~600 items in project; 457 warnings across all items
normal development state with all components loaded (many warnings, no errors)

Merged callees for ProblemsLabelDecorator.getErrorTicksFromMarkers()
before: 7427 GCed objects, 284632 GCed size
after (using recursion on packages): 1560 GCed objects, 62200 GCed size
after (visitor, no recursion): 648 GCed objects, 26048 GCed size 
- improvement: 91% less garbage

Merged callees for JavaUILabelProvider.getImage(Object)  (625 calls)
before: 21637 GCed objects, 710728 GCed size
after (visitor, no recursion): 14734 GCed objects, 447152 GCed size
- improvement: 37% less garbage


Regarding "using recursion on packages" vs. "visitor, no recursion": this has to do with the decision on when to use recursiveFindMaxSeverity vs. visitorFindMaxSeverity in MarkerManager.findMaxProblemSeverity.  The stats show that it's better to always use the visitor, except for the file case.  This is because asking for the child resources creates IResource objects (and paths, and arrays) which are not needed in the result.

Comment 5 Nick Edgar CLA 2007-03-14 14:05:26 EDT
The profile shows that 14K of the remaining 26K of garbage is in creating the non-sparse array from the sparse array representation in MarkerSet.getElements().
This could be avoided if it could iterate directly over the sparse representation (skipping nulls).  This could also be done in findMarkers.

Comment 6 Nick Edgar CLA 2007-03-14 14:08:02 EDT
Note that when I took the profile, I had warmed things up first, so the java model and its decorated images had already been created once.
My steps were:
- close and reopen the package explorer
- expand one of our projects (containing ~600 items, with 457 warnings across these)
- start the profile recording all object allocations
- expand src
- expand each package
- wait for garbage creation to settle down (according to the heap status indicator)
- stop the profile

The stats above are from examining the profiles before and after the code change.
Comment 7 Nick Edgar CLA 2007-03-14 14:14:34 EDT
I filed bug 177393 for the Platform/Debug case.
Comment 8 Nick Edgar CLA 2007-03-14 14:37:05 EDT
I considered providing an API that returned the counts for INFO, WARNING and ERROR  severities.  This would be a bit more general, e.g. it could perhaps be used in the Problems view's display of marker counts.  However, this one wouldn't be able to shortcut when it hits an ERROR, like findMaxSeverity does.
Comment 9 John Arthorne CLA 2007-03-14 16:18:06 EDT
I wrote a little benchmark to measure the time improvement.  The test created a workspace with 8,000 files in 400 folders, with 10 markers on each resource (120,000 markers). 100 invocations of an equivalent method to find max severity using old API took an average of 13.48 seconds.  With Nick's new method, the elapsed time was 3.64 seconds.  I tried also optimizing the MarkerSetElement[] creation, but it didn't have any further impact on time (I guess the JIT optimizes this kind of short term garbage very well).
Comment 10 Mike Wilson CLA 2007-03-14 16:30:12 EDT
+1
Comment 11 John Arthorne CLA 2007-03-14 16:39:16 EDT
Nick, one minor question: Is there a reason you commented out the expression in this line:

if (/*depth == IResource.DEPTH_INFINITE && */target.getType() != IResource.FILE)
Comment 12 John Arthorne CLA 2007-03-14 17:32:47 EDT
Re comment #11 - I assume this must have been a mistake, since the depth one and zero cases are broken with this expression commented out.  The visitor doesn't handle any depth other than infinite.
Comment 13 John Arthorne CLA 2007-03-14 17:42:40 EDT
Released.  Correctness tests added to MarkerTest. Performance tests added to BenchWorkspace. Thanks Nick!
Comment 14 Nick Edgar CLA 2007-03-15 10:55:34 EDT
I had commented out the depth check while trying to determine whether it's more efficient to use the visitor or the recursive method (see stats in comment 4).  However you're correct -- despite being faster, it's incorrect ;-) since the visitor doesn't handle depths other than infinite.  So your fix to put the code back is good.

Thanks for reviewing and releasing it, not to mention the extra benchmark.
Comment 15 Nick Edgar CLA 2007-03-15 11:12:56 EDT
I can confirm that having the depth check commented out was definitely a bug.
Test case:
- create packages a and a.b, with class Foo with an error in a.b
- Foo and a.b should have an error marker, but a should not
- a incorrectly gets an error marker with the depth check commented out

It works OK when the depth check is reinstated.
Comment 16 Nick Edgar CLA 2007-03-15 11:22:18 EDT
John, in your benchmark did you use errors or warnings?  If there were errors, the new API will short-circuit, which could hide any improvement from optimizing out the MarkerSetElement[] creation.
Comment 17 John Arthorne CLA 2007-03-15 11:57:10 EDT
I used only warnings.  The result was really a mystery to me, but it was slightly faster *without* optimizing out the MarkerSetElement[] creation. I will attach a patch for this additional optimization if you're curious. The benchmark is released in the BenchWorkspace class in org.eclipse.core.tests.resources.
Comment 18 John Arthorne CLA 2007-03-15 11:57:29 EDT
Created attachment 60966 [details]
Patch with additional optimization
Comment 19 Nick Edgar CLA 2007-03-19 10:09:48 EDT
The optimization looks good.  I can't explain why you're not seeing any speedup with it.  Without the optimization, your bench should be generating 100 * (8000 * (12 + 10*4)) ~= 40M of garbage.  Of course, this should all get scavenged very quickly, but I'd still expect to see some overhead.
Comment 20 Nick Edgar CLA 2007-03-19 10:11:36 EDT
It's -possible- that the JIT does escape analysis and realizes (after inlining) that the array does not live beyond the method in which it's created, and thus stack-allocates it.  But I don't think our JIT does escape analysis.
Comment 21 Nick Edgar CLA 2007-03-21 09:54:28 EDT
So in the "learn something new every day" category, one of our lead engineers on the VM team reports: "Yes, the JIT does very agressive escape analysis, and has done for a couple of releases." 

John, which VM were you using?
Comment 22 John Arthorne CLA 2007-03-21 10:23:54 EDT
J9, of course!  That's cool to hear. It goes to show that the only way to optimize is to write benchmarks to test your changes - you can never tell what changes will actually impact performance.