Bug 228017 - StyledCellLabelProvider wastes CPU in TableItem#getBounds(..) even if owner draw disabled
Summary: StyledCellLabelProvider wastes CPU in TableItem#getBounds(..) even if owner d...
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.4   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.4 RC1   Edit
Assignee: Boris Bokowski CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
Depends on: 228285 228286
Blocks: 196140
  Show dependency tree
 
Reported: 2008-04-21 10:29 EDT by Markus Keller CLA
Modified: 2008-05-06 17:02 EDT (History)
3 users (show)

See Also:


Attachments
suggested fix (1.97 KB, patch)
2008-04-22 11:56 EDT, Martin Aeschlimann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Keller CLA 2008-04-21 10:29:16 EDT
HEAD

StyledCellLabelProvider uses a lot of CPU in TableItem#getBounds(..) for each call to update(ViewerCell), even if owner draw is disabled. At least when owner draw is disabled, the manual refresh is unnecessary.

To see one instance of the performance problem, disable colored labels, run the JUnit test attached to bug 196140 comment 2, switch to Show Tests in Hierarchy, and then toggle Show Failures Only. This took about 2s in 3.3.2, but more than 20s in HEAD.

Adding
		if (isOwnerDrawEnabled())
in StyledCellLabelProvider.update(ViewerCell) solved the problem for me, but I'm not sure whether that's the right fix. Maybe it should be done in OwnerDrawLabelProvider, because that class already allows to toggle owner traw with setOwnerDrawEnabled(..).

I'm investigating whether the JUnit view could do anything to improve the situation when colored labels are enabled. I think the brute-force redrawing of every updated cell could also be improved.
Comment 1 Markus Keller CLA 2008-04-21 10:50:18 EDT
I tried to avoid updating of individual items: I set the TableViewer's input to null, remove the filter, and then set the input again. But this also triggers a call to #getBounds(..) for every item in the table.

I really don't know how I could solve the performance problems from bug 228017 while keeping the labels colored (apart from using a virtual table, which is not an option for 3.4).
Comment 2 Markus Keller CLA 2008-04-21 11:36:04 EDT
(In reply to comment #0)
> Adding
>                 if (isOwnerDrawEnabled())
> in StyledCellLabelProvider.update(ViewerCell) solved the problem for me, [..]

That breaks when owner draw gets disabled. When I toggle the preference, colored items don't lose their color until they are redrawn.
Comment 3 Martin Aeschlimann CLA 2008-04-21 11:53:36 EDT
This is the code in OwnerDrawLabelProvider:

public void update(ViewerCell cell) {
  // Force a redraw
  Rectangle cellBounds = cell.getBounds();
  cell.getControl().redraw(cellBounds.x, cellBounds.y, cellBounds.width,
  cellBounds.height, true);
}

Clearly no call to this code is needed if there is no owner draw is enabled (I'll fix this)

And I'm wondering if it is required at all.
item.setText(..) also seems to issue a refresh, even in owner draw mode.

Question to Steve. Is that intended or a bug?








Comment 4 Martin Aeschlimann CLA 2008-04-21 11:54:44 EDT
ok, as Markus mentions. The only time we really need the redraw at the moment is when the only change is a change in the colored ranges.
Comment 5 Steve Northover CLA 2008-04-21 13:01:13 EDT
It issues a refresh for the area that would be changed if there was no owner draw (on Windows, this can refresh the whole row).  I think SWT should be changed to guaratee that the entire row is refreshed.
Comment 6 Eric Moffatt CLA 2008-04-21 16:10:16 EDT
Martin, are you going to take this defect?
Comment 7 Martin Aeschlimann CLA 2008-04-21 17:01:15 EDT
> I think SWT should be
> changed to guaratee that the entire row is refreshed.

So if I understand this right, we don't need to force a redraw in owner draw mode if we know that at least the text, the image, for- and background color or font has changed on the item, correct?

What bugs me a bit: Most label providers are also font and color providers and so practically every update sets everything (text, image, font, ...) on an item. Each set does a redraw.
Is there any way to set them all at once, or delay the redraw until all is set?

Comment 8 Martin Aeschlimann CLA 2008-04-22 11:54:09 EDT
> Most label providers are also font and color providers and
> so practically every update sets everything (text, image, font, ...) on an
> item. Each set does a redraw.
I just found out that's not true, at least not on WinXP. Each set just invalidates the corresponding rectangle and WinXP paints everything later.
Comment 9 Martin Aeschlimann CLA 2008-04-22 11:56:07 EDT
Created attachment 97037 [details]
suggested fix

A patch to avoid the redraw code in OwnerDrawLabelProvider. It compares the old and new style ranges and if there's a difference, it makes sure that there is a refreh by forcing a label change on the item.
Comment 10 Steve Northover CLA 2008-04-22 13:21:53 EDT
... or we could figure out what is going in in SWT and fix it there.
Comment 11 Boris Bokowski CLA 2008-04-22 13:23:39 EDT
Martin, your patch does not remove the call to getBounds, was that intentional?
Comment 12 Boris Bokowski CLA 2008-04-22 14:50:13 EDT
I am going to investigate this some more.
Comment 13 Boris Bokowski CLA 2008-04-22 17:10:55 EDT
There are two problems here, one having to do with getBounds, and another one related to removing all but one table item.

I have opened new bugs against SWT: bug 228285 for getBounds, and bug 228286 for remove.

I am keeping this bug open - depending on the resolution of bug 228285, we should try to avoid calling getBounds.
Comment 14 Martin Aeschlimann CLA 2008-04-23 05:18:19 EDT
(In reply to comment #11)
> Martin, your patch does not remove the call to getBounds, was that intentional?

As only implementors of update(cell) know if they really changed anything, I think we can't solve this in general.
And as OwnerDrawLabelProvider.update has been around since 3.3, I'm hesitating to remove the code there. 
But it would be nice to avoid the call to cell.getBounds() in update as for computing the bounds so much is involved. It would be nicer to use something like item.repaint() and let SWT decide how this is done most efficiently.

My patch for the DelegatingStyledCellLabelProvider avoids the call to super.update (and getBounds) by making the assumption that changing the text of the Tree/TableItem will repaint the item (I hope that assumption is correct). 
Comment 15 Martin Aeschlimann CLA 2008-05-06 06:17:03 EDT
Boris, can you release the patch from comment 9?
Comment 16 Boris Bokowski CLA 2008-05-06 17:02:34 EDT
I've taken Martin's request to release the patch as his +1. Released to HEAD. Will be in the 20080507 I build.