Bug 403178 - [block selection] Block selection slower for large selections
Summary: [block selection] Block selection slower for large selections
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.3   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 4.4 M3   Edit
Assignee: Niraj Modi CLA
QA Contact:
URL:
Whiteboard: fix candidate
Keywords: noteworthy, performance
Depends on:
Blocks: 420057
  Show dependency tree
 
Reported: 2013-03-13 08:40 EDT by Szymon Ptaszkiewicz CLA
Modified: 2013-10-25 08:53 EDT (History)
4 users (show)

See Also:


Attachments
SWT patch v.0.1 (1.80 KB, patch)
2013-03-16 12:31 EDT, Szymon Ptaszkiewicz CLA
no flags Details | Diff
Text patch v.0.1 (3.33 KB, patch)
2013-03-16 12:32 EDT, Szymon Ptaszkiewicz CLA
no flags Details | Diff
SWT patch v.0.2 + TestCases (4.58 KB, patch)
2013-10-04 09:16 EDT, Niraj Modi CLA
no flags Details | Diff
SWT patch v.0.3 + TestCases (4.46 KB, patch)
2013-10-10 12:10 EDT, Niraj Modi CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Szymon Ptaszkiewicz CLA 2013-03-13 08:40:56 EDT
Steps to reproduce:
1. Create a file with many long lines (500+).
2. Enable block selection mode.
3. Put cursor at (1,1).
4. Press Shift + down arrow and hold it.
=> Observe how scrolling gets slower when selection gets bigger.

I did some initial investigation and it turns out that slowdown is caused by the fTextWidget.getSelectionCount() calls invoked from here:

Thread [main] (Suspended (breakpoint at line 3950 in TextViewer))	
	owns: RunnableLock  (id=7773)	
	SourceViewer(TextViewer).canDoOperation(int) line: 3950	
	SourceViewer.canDoOperation(int) line: 802	
	TextOperationAction.update() line: 154	
	TextEditor(AbstractTextEditor).updateAction(String) line: 5427	
	TextEditor(AbstractTextEditor).updateSelectionDependentActions() line: 5500	
	AbstractTextEditor$17.run() line: 3135	
	RunnableLock.run() line: 35	
	UISynchronizer(Synchronizer).runAsyncMessages(boolean) line: 135	
	Display.runAsyncMessages(boolean) line: 4145	
	Display.readAndDispatch() line: 3762	
	...
Comment 1 Szymon Ptaszkiewicz CLA 2013-03-13 08:45:27 EDT
I checked all calls to StyledText.getSelectionCount() in the jface.text project and it is always compared to 0. That means we don't really care about length of the selection, we just need to know if selection is empty or not. If we cannot get rid of the calls shown in comment 0, I think it is worth to consider adding StyledText.isSelectionEmpty(). In case of the scenario above, line selection is an empty string and overall block selection contains only line delimiters which means we can tell if selection is not empty right after the first line. The implementation of StyledText.isSelectionEmpty() could look like StyledText.getSelectionCount() with inlined optimized version of StyledText.getBlockSelectionText(String). Optimization would be to return true when buffer is not empty (I guess we could even get rid of the buffer itself).

I guess having StyledText.isSelectionEmpty() could give performance improvement across the whole jface.text plugin.
Comment 2 Dani Megert CLA 2013-03-13 08:46:44 EDT
(In reply to comment #0)
> Steps to reproduce:
> 1. Create a file with many long lines (500+).

What is "long" for you? For me 100 chars is already (too) long ;-).
Which editor?
Do you see the same in the TextEditor SWT Example?
Comment 3 Szymon Ptaszkiewicz CLA 2013-03-13 08:55:07 EDT
(In reply to comment #2)
> (In reply to comment #0)
> > Steps to reproduce:
> > 1. Create a file with many long lines (500+).
> 
> What is "long" for you? For me 100 chars is already (too) long ;-).
> Which editor?
> Do you see the same in the TextEditor SWT Example?

100 chars should be fine :-) I wrote "long" so that you can observe slowdown around 200th line (in my case). I tested also a file with several thousand of empty lines and it is also reproducible there, you just need to select more lines. You will see the slowdown either way, only selection needs to be "big" enough ;-)

The bug happens in any editor that uses org.eclipse.jface.text.TextViewer.canDoOperation(int).

Yes, I tested the same scenario in TextEditor SWT Example. Slowdown is caused by IAction's updates (see the stack in comment 0) so it is not reproducible in TextEditor SWT Example.
Comment 4 Szymon Ptaszkiewicz CLA 2013-03-13 08:57:08 EDT
I forgot to add that non-block selection of the same size does not result in slowdown. That is what made me aware of how StyledText.getBlockSelectionText(String) is implemented.
Comment 5 Szymon Ptaszkiewicz CLA 2013-03-13 09:09:54 EDT
Dani, if you agree with analysis in comment 1, and there is no way to get rid of those calls in TextViewer.canDoOperation(int), I can prepare a patch for StyledText. This would be an API change so we would need PMC approval to fix it in M7, right?
Comment 6 Dani Megert CLA 2013-03-13 09:14:15 EDT
(In reply to comment #5)
> Dani, if you agree with analysis in comment 1, and there is no way to get
> rid of those calls in TextViewer.canDoOperation(int), I can prepare a patch
> for StyledText. This would be an API change so we would need PMC approval to
> fix it in M7, right?

Sorry, I currently don't have time to look into this, unless it becomes a critical issue. I might have some time during M7, but no promise.
Comment 7 Szymon Ptaszkiewicz CLA 2013-03-16 12:31:24 EDT
Created attachment 228530 [details]
SWT patch v.0.1
Comment 8 Szymon Ptaszkiewicz CLA 2013-03-16 12:32:03 EDT
Created attachment 228531 [details]
Text patch v.0.1
Comment 9 Szymon Ptaszkiewicz CLA 2013-03-16 12:37:35 EDT
The two patches implement solution proposed in comment 1 and fix slowdown caused by expensive calls to StyledText.getBlockSelectionText(String).
Comment 10 Dani Megert CLA 2013-05-01 05:43:37 EDT
Moving to SWT for considering the API addition during Luna.

Will work on the text part once the API is available.
Comment 11 Szymon Ptaszkiewicz CLA 2013-09-02 07:41:27 EDT
Is it possible to release this API addition for 4.4 M2?
Comment 12 Lakshmi P Shanmugam CLA 2013-09-20 09:01:17 EDT
I think we should add this, to improve block selection performance in the editor. Setting target to 4.4 M3.
Comment 13 Niraj Modi CLA 2013-10-04 09:16:37 EDT
Created attachment 236109 [details]
SWT patch v.0.2 + TestCases

Attaching an optimized SWT patch for the new API isSelectionEmpty() in StyledText class, along with related TestCases.

Note:- Unit Tested this API, but will require an end-to-end testing, as it works for me on Win7.
Comment 14 Silenio Quarti CLA 2013-10-09 21:39:42 EDT
The implementation is fine. Let's rename the API to isSelected() instead and negate the return value.  Reason:  there are cases of isSelected() in the toolkit (in List and Table). isSelectionEmpty() would be the first.
Comment 15 Niraj Modi CLA 2013-10-10 12:10:32 EDT
Created attachment 236343 [details]
SWT patch v.0.3 + TestCases

Renamed the new API to isSelected() in StyledText & negated the return value.
Comment 16 Silenio Quarti CLA 2013-10-11 18:03:00 EDT
Looks fine. Lakshmi, please review and commit the code. I marked this bug as noteworthy.

Note that we still need to add the @since tag.
Comment 17 Lakshmi P Shanmugam CLA 2013-10-22 06:05:21 EDT
Niraj, I moved the tests into test_isSelected(). Please take a look, in all our tests the test function is named after the API.

Committed the patch to master >
http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=fcd2ef1db374a0d7da46dc6ce4535f35325185a4

Thanks Niraj & Silenio!
Comment 18 Lakshmi P Shanmugam CLA 2013-10-22 06:18:42 EDT
Opened Bug 420057 to track the Text side of the fix.
Comment 19 Szymon Ptaszkiewicz CLA 2013-10-23 05:35:19 EDT
(In reply to Lakshmi Shanmugam from comment #18)
> Opened Bug 420057 to track the Text side of the fix.

I tried to update the patch for the Text part, but I get the following error:

Invalid @since 4.4 tag on isSelected(); expecting @since 3.103

Are you sure that 4.4 is correct here? I have seen many places with @since 3.102 but none with anything like @since 4.x in the SWT plugin.
Comment 20 Dani Megert CLA 2013-10-23 06:43:14 EDT
(In reply to Szymon Ptaszkiewicz from comment #19)
> (In reply to Lakshmi Shanmugam from comment #18)
> > Opened Bug 420057 to track the Text side of the fix.
> 
> I tried to update the patch for the Text part, but I get the following error:
> 
> Invalid @since 4.4 tag on isSelected(); expecting @since 3.103
> 
> Are you sure that 4.4 is correct here? I have seen many places with @since
> 3.102 but none with anything like @since 4.x in the SWT plugin.

The @since tag is wrong - it must be 3.103.
Comment 21 Silenio Quarti CLA 2013-10-23 09:47:07 EDT
(In reply to Dani Megert from comment #20)
> The @since tag is wrong - it must be 3.103.

Fixed
Comment 22 Dani Megert CLA 2013-10-24 06:39:54 EDT
(In reply to Silenio Quarti from comment #14)
> The implementation is fine. Let's rename the API to isSelected() instead and
> negate the return value.  Reason:  there are cases of isSelected() in the
> toolkit (in List and Table). isSelectionEmpty() would be the first.

When adopting this (see bug 420057), I was a bit puzzled by the name: what is selected? The widget? Any character? All characters? Actually there are no other isSelected() declarations in SWT. The ones mentioned all take an argument and hence the method name makes sense there.

I'd prefer to rename the method to #hasSelectionText(). This fits well together with #getSelectionText().
Comment 23 Silenio Quarti CLA 2013-10-24 09:54:22 EDT
(In reply to Dani Megert from comment #22)
> (In reply to Silenio Quarti from comment #14)
> > The implementation is fine. Let's rename the API to isSelected() instead and
> > negate the return value.  Reason:  there are cases of isSelected() in the
> > toolkit (in List and Table). isSelectionEmpty() would be the first.
> 
> When adopting this (see bug 420057), I was a bit puzzled by the name: what
> is selected? The widget? Any character? All characters? Actually there are
> no other isSelected() declarations in SWT. The ones mentioned all take an
> argument and hence the method name makes sense there.
> 
> I'd prefer to rename the method to #hasSelectionText(). This fits well
> together with #getSelectionText().

SWT does not have any API that starts with "has*". I would prefer not to add one now. For me isSelected() is clear. There are no parameters, so it means it applies  to the widget (receiver). If there was a parameter, it would be an offset and the API would tell whether the offset is selected.  It could be a range (start, end offsets) as well.   If the user cares whether the whole text is selected, he can call getSelectionCount().

Anyways, would getTextSelected() or isTextSelected() be better for you?
Comment 24 Dani Megert CLA 2013-10-24 10:37:34 EDT
(In reply to Silenio Quarti from comment #23)
> (In reply to Dani Megert from comment #22)
> > (In reply to Silenio Quarti from comment #14)
> > > The implementation is fine. Let's rename the API to isSelected() instead and
> > > negate the return value.  Reason:  there are cases of isSelected() in the
> > > toolkit (in List and Table). isSelectionEmpty() would be the first.
> > 
> > When adopting this (see bug 420057), I was a bit puzzled by the name: what
> > is selected? The widget? Any character? All characters? Actually there are
> > no other isSelected() declarations in SWT. The ones mentioned all take an
> > argument and hence the method name makes sense there.
> > 
> > I'd prefer to rename the method to #hasSelectionText(). This fits well
> > together with #getSelectionText().
> 
> SWT does not have any API that starts with "has*". I would prefer not to add
> one now. For me isSelected() is clear. There are no parameters, so it means
> it applies  to the widget (receiver).

Exactly and this is misleading because it is not the widget that is selected (e.g. in a page), but it is the text.


> Anyways, would getTextSelected() or isTextSelected() be better for you?

#isTextSelected() works for me, thanks.
Comment 25 Lakshmi P Shanmugam CLA 2013-10-25 08:53:47 EDT
Changed API to isTextSelected and updated the tests.
http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=5a748dd716a2f6cf95105a6f5f78eee6d06dbfc6