eclipse.platform.swt icon indicating copy to clipboard operation
eclipse.platform.swt copied to clipboard

slow StyledTextRenderer for unicode and unprintable control characters

Open jukzi opened this issue 3 years ago • 12 comments

On windows eclipse text editors sometimes lag when scrolling I sampled the times and see that most times is spend in TextLayout.getLineCount() which is called for every line in the handlePaint() loop.

As far as i understand the number of lines won't change while drawing so it should be enough to calculate the number of lines once.

image

jukzi avatar Sep 29 '22 05:09 jukzi

Turns out lineCount() is the drawn lines per lines which is ==1 without linewrap. but the shape() will be done anyway to calculate the width of the line. The slow text file contains multiple <STX><ETX> sequences per line which the default font "consolas" can not draw. Font "Courier New" does not show the performance problem even though it can't render those special chars neither.

i prefer the notepad++ way to (fast) draw meaningfull symbols instead of undrawable characters:

eclipse: image notepad++ image

jukzi avatar Sep 29 '22 11:09 jukzi

Could you please provide a short snippet where this is reproducible with pure SWT?

tmssngr avatar Feb 20 '23 13:02 tmssngr

@tmssngr here is a pure swt Example:

package org.eclipse.swt.snippets;
import org.eclipse.swt.*;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class SlowStyledTextRender414 {

  public static void main(String[] args) {
    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setLayout(new FillLayout());

    StringBuilder b=new StringBuilder();
    for (int y=0;y<1000;y++) {
    	b.append(y+" ");
	    for (int x=0;x<100;x++) {
	    	b.append("\u0002msg\u0003 ");
	 //fast:    	b.append("2msg3 ");
	    }
	    b.append("\n");
    }
    String s=b.toString();
    StyledText t = new StyledText(shell, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
    // faster: Text t = new Text(shell, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
    t.setLayoutData(new GridData(GridData.FILL_BOTH));
    t.setText(s);
    t.setFont(new Font(display,"consolas", 11, SWT.NONE ) );


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

jukzi avatar Feb 23 '23 07:02 jukzi

Thanks. I agree, this is really slow.

tmssngr avatar Feb 23 '23 11:02 tmssngr

@jukzi I am also seeing the slowness in my environment with your snippet.

Eclipse SDK Version: 2023-06 (4.28) Build id: I20230530-1800 OS: Windows 11, v.10.0, x86_64 / win32 Java vendor: Eclipse Adoptium Java runtime version: 20+36 Java version: 20

deepika-u avatar May 31 '23 06:05 deepika-u

just tested, that it is also slow for non-ascii Unicode characters that can be rendered. for example: b.append("\u0FCAmsg\u0FCA "); More over it is also visible that those characters are missing in some lines after scrolling down an up again:

image

@merks Also tested, that https://github.com/eclipse-platform/eclipse.platform.swt/issues/680#issuecomment-1558622484 does not solve this.

jukzi avatar May 31 '23 07:05 jukzi

@jukzi

I have added the line to test "non-ascii Unicode characters" after line 17 and inspite of scrolling for almost 10times(up and down) i am seeing the result consistent as below. Able to see some character always unlike yours but nothing missing. Yeah but definitely slow.

image

fyi - This time i tried with a different version of java on RC2 build. Eclipse SDK Version: 2023-06 (4.28) Build id: I20230531-1800 OS: Windows 11, v.10.0, x86_64 / win32 Java vendor: Eclipse Adoptium Java runtime version: 19.0.2+7 Java version: 19.0.2

deepika-u avatar Jun 01 '23 06:06 deepika-u

What would you think - could it be an idea to replace those "characters" below 0x20 with 0x20 before sending to the native renderer?

tmssngr avatar Aug 28 '24 05:08 tmssngr

before sending to the native renderer?

At best such characters would be rendered as meaningful symbols like notepad++ does. For example replacing https://symbl.cc/de/0002/ with https://symbl.cc/de/2402/ might be good.

It must be clarified if the performance problem is inside the native renderer or within swt source code.

jukzi avatar Aug 28 '24 05:08 jukzi

There seems to be a complete block with symbols in Unicode: https://symbl.cc/en/unicode/blocks/control-pictures/#subblock-2400

jukzi avatar Aug 28 '24 05:08 jukzi

I've sent a proof-of-concept-PR. With your snippet on my Windows 11 it makes no difference whether using \u2400... or a space - in both cases it looks the same. But it is noticeable faster.

tmssngr avatar Aug 28 '24 10:08 tmssngr

https://github.com/eclipse-platform/eclipse.platform.swt/pull/1425 is good for performance, and i can still copy&paste the right text. Too bad the fonts do not - and can not [1] - support all unicode characters especially those we could need here. A solution might be to draw text with multiple ascii characters per unsupported character. For example STX instead of "\u0002"

[1] https://stackoverflow.com/a/34734338 Unicode, contains 120,737 assigned code points - almost twice as many as fit in a modern font

jukzi avatar Aug 28 '24 13:08 jukzi