Bug 168557 - [StyledText] StyledText is very slow with long string + word wrap or other variable line height
Summary: [StyledText] StyledText is very slow with long string + word wrap or other va...
Status: REOPENED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.3   Edit
Hardware: All All
: P3 normal with 10 votes (vote)
Target Milestone: ---   Edit
Assignee: Conrad Groth CLA
QA Contact: Mickael Istria CLA
URL:
Whiteboard:
Keywords: performance
: 195559 334678 484142 559626 575200 (view as bug list)
Depends on: 577649
Blocks: 35779 407405 535326 560449 563531
  Show dependency tree
 
Reported: 2006-12-19 10:45 EST by Grant Gayed CLA
Modified: 2023-06-04 14:25 EDT (History)
34 users (show)

See Also:


Attachments
inside setCaretLocation computing the caretLocation again (140.92 KB, image/png)
2020-03-29 15:27 EDT, Conrad Groth CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Grant Gayed CLA 2006-12-19 10:45:00 EST
3.3M4

The following snippet takes a couple of seconds to run on my machine if I substitute Text for StyledText.  However with StyledText it appears to hang (it would probably finish eventually, but after a couple of minutes I stopped it).

public static void main(String[] args) {
    Display display = new Display ();
    Shell shell = new Shell(display);
    shell.setBounds(10,10,300,300);
    final StyledText text = new StyledText (shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP);
    text.setBounds(10,10,280,200);
    int count = 0;
    String[] strings = new String[7];
    for (int i = 0; i < 7; i++) {
        String string = "";
        for (int j = 0; j <= i; j++) {
            string += (char)(65 + j);
        }
        strings[i] = string;
    }
    int index = 0;
    final StringBuffer buffer = new StringBuffer();
    while (count < (1024 * 1024 * 1.3)) {
        buffer.append(strings[index++]);
        buffer.append(" ");
        count += index;
        if (index == 7) index = 0;
    }
    shell.open ();
    text.setText(buffer.toString());
    while (!shell.isDisposed ()) {
        if (!display.readAndDispatch ()) display.sleep ();
    }
    display.dispose ();
}
Comment 1 Felipe Heidrich CLA 2007-07-05 15:03:52 EDT
It is because wrapword is on.
Comment 2 Felipe Heidrich CLA 2007-07-05 15:04:25 EDT
*** Bug 195559 has been marked as a duplicate of this bug. ***
Comment 3 Felipe Heidrich CLA 2009-08-21 15:09:28 EDT
Your bug has been moved to triage, visit http://www.eclipse.org/swt/triage.php for more info.
Comment 4 Helmut Neubauer CLA 2010-01-11 17:03:02 EST
(In reply to comment #1)
> It is because wrapword is on.

But it should be possible to use word wrap without performance lost. I'll use 100 lines à 50 letters and the response time slows down rapidly. I took a swing component in an older project and there was no performance lost with hundreds of lines in one paragraph. 

Please have a look at this component and improve the performance with word wrap.
Comment 5 Vadim Korkin CLA 2013-09-29 15:23:31 EDT
Hi all,

I'm new to eclipse but I want to create a program that works with large text files (logs) and I need StyledText functionality. So this was one of he first issues I ran into. I made some research in the swt code and found the main causes of he slow response:

1. When the user has two MParts with a StyledText in them and clicks on tab so that he tab that was active becomes inactive abd the inactive one becomes active the method StyledText.computeSize is called some value for wHint and -1 for hHint. This method recalculates all lines even though nothing has changed! the width is the same the font is the same etc. I made a subclass of StyledText where I call super.computeSize only when the width has changed. After that I could switch between MParts without any delay

2. The second issue is related to CSS styling. When a CSS styling is enabled he parameters defined in the CSS are always set when for example a Dialog is shown above the StyledText. When a font of the background is set he cache with line heights and widths is reset. setFont calls resetCache(0, content.getLineCount()); And all data is removed and has to be recalculated every time. But in fact nothing has changed because the CSS always sets the same font, background ect. What I suggest is adding a check to the method that set a parameter and resets the cache that the parameter is different from the one already in place. I added the following to my class StyledText2:

public void setFont(Font font) {
        if (!getFont().equals(font)) {
            super.setFont(font);
        } else {
            log.info("Setting the same font ignoring no redraw");
        }
    }

After making changes 1 and 2 I only experience delays when the text is loaded and the cache is empty. After I scroll down to the last line the cache is loaded with values and it works as fast as without WRAP. But I don't think this can be avoided - the right height has to be calculated at least once.

The bottom line: I don't mind contributing but I'm relatively new to Eclipse I've been working with the framework and SWT for 3 months only. And I have never contributed anything. Maybe my changes are wrong or won't work in some cases. Could someone comment on my ideas? Does it all make sense?
Comment 6 Christopher Mindus CLA 2015-06-18 15:39:58 EDT
I find it amazing that this issue is not resolved, and in Mars (4.5), considering that this was reported under 3.3.

The StyledText is unusable with word wrap turned on for longer strings than 1000 characters, even on a 4.3GHz clocking CPU!

I've tried workarounds with setRedraw and others, but everything happens during a sendEvent in the code "down under", so it's not too easy to figure out where the problem lies.

I guess the workaround is to use AWT JEditorPane instead of SWT StyledText.
Comment 7 Niraj Modi CLA 2015-12-08 00:34:16 EST
(In reply to Christopher Mindus from comment #6)
> The StyledText is unusable with word wrap turned on for longer strings than
> 1000 characters, even on a 4.3GHz clocking CPU!

Tested same with Eclipse on Win7 with 'word wrap' option ON, was able to successfully open a file with with 30K characters in single line:
Preference > General > Editors > Text Editors > "Enable word wrap when opening an editor"
Yes, with 'word wrap' option OFF, I can notice that entire line becomes invisible which is another bug 23406.

Additionally tested with snippet in comment 0, StyleText works with around 30K characters, beyond that it doesn't work properly.
Will investigate this further.
Comment 8 Niraj Modi CLA 2016-03-21 07:18:03 EDT
(In reply to Niraj Modi from comment #7)
> (In reply to Christopher Mindus from comment #6)
> > The StyledText is unusable with word wrap turned on for longer strings than
> > 1000 characters, even on a 4.3GHz clocking CPU!
> 
> Tested same with Eclipse on Win7 with 'word wrap' option ON, was able to
> successfully open a file with with 30K characters in single line:
> Preference > General > Editors > Text Editors > "Enable word wrap when
> opening an editor"
30K in single line looks acceptable to me.. deferring this bug for now.
Comment 9 Jonah Graham CLA 2018-06-05 07:05:46 EDT
I have been running this on Linux, but on Windows I and others have seen the same thing.

Here is an updated snippet that shows the kind of problem we are facing in CDT with long build outputs. On my very fast machine it takes a very long time (> 20 seconds) to scroll to the end of the StyledText without the ranges on. The whole time the UI thread is in use and therefore the UI is frozen. The same types of issues happen if you open any large file - like a log file - in any editor and turn on line wrapping.

Running this size input in other environments (LibreWriter, gedit, google chrome) it takes a long time to render the whole file. However in those cases the UI remained responsive and the scroll bar just kept growing as it rendered. And once rendered once there was no performance issue, you can resize, etc.

VS code hung for a few seconds, but then was fully responsive.

Emacs just worked entirely and instantly.



public class Snippet {

	private static final int LINES = 500000;
	private static final int LINES_PER_RANGE_CHANGE = 10;
	private static final int WORDS_PER_LINE = 10;
	private static final String WORD = "123456789 ";

	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setBounds(10, 10, 300, 300);
		shell.setLayout(new FillLayout());
		final StyledText text = new StyledText(shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP);
		Color red = new Color(display, 255, 0, 0);

		StringBuilder buffer = new StringBuilder(LINES * WORDS_PER_LINE * WORD.length() * 2);
		StyleRange[] ranges = new StyleRange[LINES / LINES_PER_RANGE_CHANGE * 2];
		for (int i = 0; i < LINES / LINES_PER_RANGE_CHANGE; i++) {
			int start = buffer.length();
			for (int k = 0; k < LINES_PER_RANGE_CHANGE - 1; k++) {
				buffer.append("Group " + i + " Line " + k + ": ");
				for (int j = 0; j < WORDS_PER_LINE; j++) {
					buffer.append(WORD);
				}
				buffer.append("\n");
			}
			int length = buffer.length() - start;
			ranges[i * 2] = new StyleRange(start, length, null, null);

			int startHighlight = buffer.length();
			buffer.append("Group " + i + " Highlight" + ": ");
			for (int j = 0; j < WORDS_PER_LINE; j++) {
				buffer.append(WORD);
			}
			buffer.append("\n");
			int lengthHighlight = buffer.length() - startHighlight;
			ranges[i * 2 + 1] = new StyleRange(startHighlight, lengthHighlight, red, null);
		}
		
		
		shell.open();
		text.setText(buffer.toString());
		// Uncomment to test with ranges, not sure it makes a big
		// difference  
		// text.setStyleRanges(ranges);
		System.out.println("Total buffer length: " + buffer.length());
		System.out.println("Total number of ranges: " + ranges.length);

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}


The stack trace I normally see looks like this or similar:

Thread [main] (Suspended)	
	OS._pango_layout_set_text(long, byte[], int) line: not available [native method]	
	OS.pango_layout_set_text(long, byte[], int) line: 16949	
	TextLayout.computeRuns() line: 158	
	TextLayout.getBoundsInPixels() line: 810	
	TextLayout.getBounds() line: 799	
	StyledTextRenderer.calculate(int, int) line: 217	
	StyledTextRenderer.getLineHeight(int) line: 568	
	StyledText.calculateTopIndex(int) line: 1611	
	StyledText.scrollVertical(int, boolean) line: 8140	
	StyledText.handleVerticalScroll(Event) line: 6430	
	StyledText$9.handleEvent(Event) line: 5769	
	EventTable.sendEvent(Event) line: 84	
	Display.sendEvent(EventTable, Event) line: 5227	
	ScrollBar(Widget).sendEvent(Event) line: 1340	
	Display.runDeferredEvents() line: 4561	
	Display.readAndDispatch() line: 4151	
	Snippet.main(String[]) line: 58
Comment 10 Ashish Mathur CLA 2018-08-02 05:53:50 EDT
Is there a prospect of this being addressed in the near future ?
Comment 11 Andrey Loskutov CLA 2020-01-28 09:33:22 EST
*** Bug 334678 has been marked as a duplicate of this bug. ***
Comment 12 Lars Vogel CLA 2020-01-28 09:44:21 EST
*** Bug 559626 has been marked as a duplicate of this bug. ***
Comment 13 Eclipse Genie CLA 2020-03-14 20:29:50 EDT
New Gerrit change created: https://git.eclipse.org/r/159376
Comment 14 Niraj Modi CLA 2020-03-17 03:08:15 EDT
(In reply to Eclipse Genie from comment #13)
> New Gerrit change created: https://git.eclipse.org/r/159376

Will verify shortly.
Comment 15 Mickael Istria CLA 2020-03-22 09:29:08 EDT
*** Bug 484142 has been marked as a duplicate of this bug. ***
Comment 16 Conrad Groth CLA 2020-03-29 15:27:55 EDT
Created attachment 282265 [details]
inside setCaretLocation computing the caretLocation again
Comment 18 Mickael Istria CLA 2020-03-30 15:46:46 EDT
@Conrad: thanks for the patch. Anything left to do before we can mark this one as resolved.
Comment 19 Niraj Modi CLA 2020-04-03 06:27:39 EDT
(In reply to Mickael Istria from comment #18)
> @Conrad: thanks for the patch. Anything left to do before we can mark this
> one as resolved.

Quick check on how was the performance improvement observed/measured with new Snippet376.java or any other Eclipse view ?
Comment 20 Niraj Modi CLA 2020-04-06 06:53:02 EDT
(In reply to Niraj Modi from comment #19)
> (In reply to Mickael Istria from comment #18)
> > @Conrad: thanks for the patch. Anything left to do before we can mark this
> > one as resolved.
> 
> Quick check on how was the performance improvement observed/measured with
> new Snippet376.java or any other Eclipse view ?

Ping!
Comment 21 Conrad Groth CLA 2020-04-06 11:39:06 EDT
I checked with Snippet376.java. To find the bottlenecks I attached Yourkit to Snippet376 and scrolled and resized the snippet shortly after start. It will immediately freeze without the patch. With the patch Snippet376 should be smoothly scrollable and resizable.

Nothing left from my point of view.
Comment 22 Sravan Kumar Lakkimsetti CLA 2020-04-08 03:52:49 EDT
Verified on Ubuntu 18.04 using
Eclipse SDK
Version: 2020-06 (4.16)
Build id: I20200407-1800
OS: Linux, v.4.15.0-96-generic, x86_64 / gtk 3.22.30
Java version: 1.8.0_242
Comment 23 Niraj Modi CLA 2020-04-08 06:22:29 EDT
(In reply to Conrad Groth from comment #21)
> I checked with Snippet376.java. To find the bottlenecks I attached Yourkit
> to Snippet376 and scrolled and resized the snippet shortly after start. It
> will immediately freeze without the patch. With the patch Snippet376 should
> be smoothly scrollable and resizable.
> 
> Nothing left from my point of view.

(In reply to Sravan Kumar Lakkimsetti from comment #22)
> Verified on Ubuntu 18.04 using
> Eclipse SDK
> Version: 2020-06 (4.16)
> Build id: I20200407-1800
> OS: Linux, v.4.15.0-96-generic, x86_64 / gtk 3.22.30
> Java version: 1.8.0_242

Thanks for testing the fix, marking as Verified.
Comment 24 Andrey Loskutov CLA 2020-05-25 06:27:23 EDT
This fix caused severe regression, see bug 563531. Please check if a quick fix is possible or if we should revert it for 4.16.
Comment 25 Eclipse Genie CLA 2020-05-26 01:40:24 EDT
New Gerrit change created: https://git.eclipse.org/r/163569
Comment 26 Niraj Modi CLA 2020-05-26 02:07:48 EDT
(In reply to Andrey Loskutov from comment #24)
> This fix caused severe regression, see bug 563531. Please check if a quick
> fix is possible or if we should revert it for 4.16.

I confirm on above observation from Andrey, created below revert gerrit(if we are not able to find a fix for bug 563531):
https://git.eclipse.org/r/163569
Comment 27 Niraj Modi CLA 2020-05-26 06:08:17 EDT
With fix for bug 563531, which partially reverts the original fix for this issue via https://git.eclipse.org/r/163570 for 4.16 RC1

Hence, reopening to revisit this bug once again in 4.17
Comment 28 Niraj Modi CLA 2020-06-22 07:07:30 EDT
(In reply to Niraj Modi from comment #27)
> With fix for bug 563531, which partially reverts the original fix for this
> issue via https://git.eclipse.org/r/163570 for 4.16 RC1
> 
> Hence, reopening to revisit this bug once again in 4.17

Hi Conrad,
Can you revisit on this bug as bug 563531 partially reverted the original fix made by you ?
Comment 29 Niraj Modi CLA 2020-09-02 04:53:02 EDT
Mass move out to 4.18
Comment 30 Niraj Modi CLA 2020-11-24 03:15:22 EST
Please re-target as required.
Comment 31 Jonah Graham CLA 2021-12-06 10:26:40 EST
*** Bug 575200 has been marked as a duplicate of this bug. ***
Comment 32 Sam Gabriel CLA 2023-06-02 21:41:19 EDT
Any news about this bug. it is causing the console output to freeze the entire IDE
Comment 33 Mickael Istria CLA 2023-06-04 14:25:19 EDT
(In reply to Sam Gabriel from comment #32)
> Any news about this bug. it is causing the console output to freeze the
> entire IDE

Can you please reopen this bug against the SWT tracker https://github.com/eclipse-platform/eclipse.platform.swt/issues with details to reproduce it using latest release or latest build?