Bug 27862 - Tree.setSelection() takes > 1 second
Summary: Tree.setSelection() takes > 1 second
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 2.1   Edit
Hardware: PC Linux-GTK
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Christophe Cornu CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
Depends on:
Blocks:
 
Reported: 2002-12-06 14:38 EST by Luc Bourlier CLA
Modified: 2002-12-11 09:45 EST (History)
3 users (show)

See Also:


Attachments
optimizeit1.png profiling result for a step over (106.42 KB, image/png)
2002-12-06 14:39 EST, Luc Bourlier CLA
no flags Details
optimizeit2.png - profiling for a step in (105.15 KB, image/png)
2002-12-06 14:40 EST, Luc Bourlier CLA
no flags Details
Tree.setSelection called 27 times, 25 times on same tree with same parameters (55.21 KB, text/plain)
2002-12-09 19:06 EST, Christophe Cornu CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Luc Bourlier CLA 2002-12-06 14:38:49 EST
Since some builds, the step over action in the debugger is slow on GTK (see bug
25516). Other actions (step in/out) work fine, step over works fine on motif and
win32.

I did some profiling with OptimizeIt. The result is, when we refresh the debug
(launch) view after the step, one call to Tree.setSelection() takes > 1 second
(see the screenshots below).

For my test, I use the following compilation unit :

public class Test {
  public static void main(String[] args) {
    new Test().recursif(20);
  }
  void recursif(int i) {
    if (i == 0) {
      String s= null;
      s= null;              // <-- breakpoint here
      s= null;
      System.out.println(s);
    } else {
      recursif(i - 1);
    }
  }
}
Comment 1 Luc Bourlier CLA 2002-12-06 14:39:50 EST
Created attachment 2687 [details]
optimizeit1.png profiling result for a step over
Comment 2 Luc Bourlier CLA 2002-12-06 14:40:26 EST
Created attachment 2688 [details]
optimizeit2.png - profiling for a step in
Comment 3 Christophe Cornu CLA 2002-12-09 09:07:40 EST
Chrix to investigate and advise
Adding Silenio to the CC list

Need to check:
- nbr of calls to Tree.setSelection (e.g. by setting OptimizeIt 
in 'instrumentation' mode)
- Characteristics of the Tree, selection, and impact on performance
Comment 4 Christophe Cornu CLA 2002-12-09 19:03:50 EST
Luc:

Tested on GTK with I20021204 and on Windows with I20021127

On Step Over in the example given above, Tree.setSelection is called 27 times.
The first 25 times seem to be exactly identical (same tree, same selection).
Step Into/Step Return don't have that problem.
If setting the level of recursion to 30, SWT gets 35 identical calls.

You can check this by either
- importing org.eclipse.swt to your project and adding a println to
Tree.setSelection
- run OptimizeIt and select 'instrumentation' instead of the default 'sampling'
(ask for more details on this if needed)

Can you confirm that this is happening?
Are all these Tree.setSelection required? Or the symptom of a problem somewhere
else?

I attach a log of the stack traces next.
Thanks
Chris
Comment 5 Christophe Cornu CLA 2002-12-09 19:06:29 EST
Created attachment 2737 [details]
Tree.setSelection called 27 times, 25 times on same tree with same parameters
Comment 6 Jared Burns CLA 2002-12-09 22:40:17 EST
We're calling StructuredViewer.refresh(Object). Why is this causing the
selection to be set? The API on this method doesn't say anything about setting
the selection.
Comment 7 Christophe Cornu CLA 2002-12-10 11:37:47 EST
Nick here.  The viewer refresh tries to preserve the selection across the refresh.  
It gets the selection before doing the refresh work, then sets it back after.
This is to ensure that the user's selection is unaffected (or as minimally affected 
as possible) by the refresh.  For example, if a refresh causes a reordering of 
elements, you don't want your selection to be lost.

Looking at the stack traces captured above, it looks like refresh is being called 
many more times than needed.  A comment in the code suggests that Debug is 
calling this to force population of the items so that setSelection works.  However, 
AbstractTreeViewer.setSelection already does this for you (the call to 
internalExpand).  This relies on ITreeContentProvider.getParent actually returning 
a parent element though, which may be problematic in your case.
Why can't you just call setSelection(element, true), or expandToLevel(element, 1)?
Comment 8 Jared Burns CLA 2002-12-10 11:43:17 EST
I'm looking at making the code on our end do less. We were trying to be clever
and only refresh the children of a tree node instead of just refreshing the
node itself. I've found that by gutting our code of all wit, stepping is much
faster. :)
Comment 9 Nick Edgar CLA 2002-12-10 12:31:18 EST
I'd like to understand why you need to do the refresh at all.  Refreshes are 
expensive, and I don't think it should be necessary just to select and reveal 
an element.
Comment 10 Jared Burns CLA 2002-12-10 12:45:02 EST
In our case, we're responding to suspend events after a Step in the debugger.
We need to refresh the thread to update the stack frames. When the number
of frames changes (StepIn, StepReturn) we need to add/remove frames. When
the number of frames stays the same (StepOver), we need to update the labels
of the frames (at least the top frame and the thread label).
Comment 11 Nick Edgar CLA 2002-12-10 13:01:58 EST
Note that if you only want to update labels, and not the structure, you should 
use the update methods on the individual elements rather than refresh on the 
parent.  Update does not recurse.


Comment 12 Jared Burns CLA 2002-12-10 15:22:20 EST
Thanks for the info.

Regarding the bug report, it turns out that calling refresh on all of the
items is just as slow on Win32. We fixed our code (stepping is *much* faster
now).

We found that refreshing ~40 tree items made a step take about 1 second
on a fast machine. Unless this is considered poor performance, this report can
be closed.
Comment 13 Christophe Cornu CLA 2002-12-10 16:11:55 EST
As found in this PR, Tree.setSelection/StructuredViewer.refresh are not cheap and 
may be overkill in some situations.
Cheaper alternative APIs have been found, fixing the original performance problem.
Closing PR.

BTW, continue to report 'slow SWT calls' you may find impacting some Eclipse use 
case. This helps everybody understand the chain of calls and work it out. Thanks.
Comment 14 Nick Edgar CLA 2002-12-10 16:55:34 EST
Sorry, but 1 second to step on a fast machine still sounds pretty slow.
Are you still using refresh?  I still don't understand why a refresh is needed.
Comment 15 Jared Burns CLA 2002-12-10 18:10:07 EST
I don't think I was clear. :-)

We're only calling refresh 1 time now in our code. Stepping is blazingly fast.

However, the fact remains that when we did call refresh 40 times (back in
the long, long ago), it took about 1 second for those 40 refreshes to occur.
In CPU-time, 1 second to do something 40 times would usually be considered
bad so there might still be some performance work to be done here.
Comment 16 Nick Edgar CLA 2002-12-11 09:45:00 EST
I'm still not clear on why you need to do the refresh at all.
If it's to show new stack frames, is there any way you could use add() and 
remove() instead?  If it's just to update the label for the topmost one, you 
should just use the update method.