Bug 5386 - StyledText (bidi) - performance improvements
Summary: StyledText (bidi) - performance improvements
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 1.0   Edit
Hardware: PC All
: P3 normal (vote)
Target Milestone: 2.0 M2   Edit
Assignee: Knut Radloff CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2001-10-31 11:08 EST by Lynne Kues CLA
Modified: 2002-01-14 17:55 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Lynne Kues CLA 2001-10-31 11:08:55 EST
PR to keep track of performance issues, solutions, etc. on the bidi platform.
Comment 1 Knut Radloff CLA 2001-10-31 13:38:41 EST
Changed StyledText.getBidiSegmentsCompatibility to return immediately when 
bidiColoring is false. It used to always call getLineStyleData.
Comment 2 Knut Radloff CLA 2001-10-31 16:20:49 EST
Reusing StyledTextBidi objects cuts the time to the line 
"internalSetSelection(selection.x + newLength - replacedLength, selection.y - 
selection.x, true);" at the end of StyledText.java with java syntax colors and 
bolding in the use case from 5.5 seconds to 4 seconds (~25%).
There are 108 StyledTextBidi objects being created instead of 450 without the 
optimizations.
The only drawback is that we have to pass in the GC whenever it is needed by 
StyledTextBidi API. This is because the life of a StyledTextBidi object now 
exceeds the life of a GC. There are five methods that require the additional GC 
argument.
An added bonus of this optimization is that getting a StyledTextBidi object 
would be as easy as calling getBidiInstance(lineText, lineOffset). The code 
would no longer be littered with getting styleRanges from the listener and GC 
creation and disposal.
Comment 3 Knut Radloff CLA 2001-11-01 17:29:43 EST
Caching StyledTextBidi
----------------------
This is actually quite problematic because of the variables that necessitate a 
new object. The cache needs to be reset whenever the line text, font or styles 
change. The line text and font can easily be associated with the cached object 
and compared with the requested state. 
Comparing the styles would be more involved and could potentially negate the 
savings introduced by the cache. Instead the cache should be reset whenever the 
styles are changed which can happen either by calling 
setStyleRange/setStyleRanges API or in a LineStyleListener. Therefore the cache 
would need to be reset in the API and in all the public redraw methods.
Even if we decide not to cache the StyledTextBidi object we could still use the 
cache infrastructure to simplify object creation.
Comment 4 Knut Radloff CLA 2001-11-01 17:33:47 EST
Summary of discussion with LK:
-Disable StyledTextBidi cache. See comments above.
-Move content width calculation into drawLine and only set horizontal scrollbar 
when necessary. Reduces creation of StyledTextBidi objects.
-Identify code paths with duplicate calls to getLineStyleData/multiple creation 
of bidi objects, in particular in modifyContent.
Comment 5 Knut Radloff CLA 2001-11-05 15:04:20 EST
Content width calculation during rendering (drawLine)
-----------------------------------------------------
There are a few problems with this approach.
Since redraw resets the content width for the affected lines and the new width 
is calculated later, during rendering, there is a time when the current content 
width (and the horizontal scroll bar) does not reflect the actual width of the 
displayed lines. This becomes a problem when the uncalculated line is used for 
measuring (e.g., getLocationAtOffset on the longest line) and the result is 
then used to set the horizontal scroll position. Scrolling will be wrong and 
the scoll bar will not be positioned properly because the content width does 
not yet include the changed line.
There are related problems internal to StyledText that we could workaround. 
However, in general the content width and horizontal scroll bar always have to 
reflect the widest visible line immediately after a potentially width changing 
operation (e.g., a call to redraw may indicate that a LineStyleListener has 
changed styles which may affect the line width).
Comment 6 Lynne Kues CLA 2001-11-06 16:33:52 EST
Changed getLigatureStart/End offset code to not test for a ligated font.  Helps 
with the number of platform calls during getLineStyleData when dealing with 
ligatures.
Comment 7 Lynne Kues CLA 2001-11-12 14:57:05 EST
Added a new method to BidiUtil which calls GCP and only requests ordering 
information (vs. both ordering and rendering information).  This leads to about 
a 20% speed improvment for those GCP calls that just need ordering information.
Comment 8 Knut Radloff CLA 2001-11-12 19:07:08 EST
Changed StyledText.showBidiCaret code path to use just one StyledTextBidi 
object. It no longer calls getXAtOffset but does the work directly and then 
passes the same bidi object in to setBidiCaretLocation. This speeds up the 
modifyContent path by about 15% and the showBidiCaret (which is the second 
largest item in modifyContent) by about 40%.
Comment 9 Knut Radloff CLA 2001-11-13 14:05:50 EST
Changed StyledText.showCaret to pass in already calculated caret x location and 
line index to setCaretLocation.
Speeds up modifyContent by about 10% and showCaret by 40%. Effect in Eclipse 
20011106 on Windows is not very noticable though.
Comment 10 Knut Radloff CLA 2001-11-14 12:04:59 EST
Reduced calls to GC.getFont/Font.getFontData during rendering and measuring.
The current font was being tracked locally in drawStyledLine and textWidth. 
This moved up a few levels (to handlePaint in the case of drawStyledLine) to 
avoid querying the current font for every line during a single paint event. 
This required moving the font querying out of textWidth and passing the current 
font as an argument instead. A benefit of this is that 
StyledText$ContentWidthCache.calculate is now faster if called for more than 
one line because it now also passes in the current font to textWidth.
drawLine is now almost 20% faster (9000 calls)
calculate is 30% faster (218 calls/4400 lines)
Comment 11 Knut Radloff CLA 2001-11-15 15:33:15 EST
Reducing calls to getXAtOffset (->getLineStyleData, getFontData) in redrawLines:

The scenario for a possible performance improvement of setStyleRange is setting 
a style for a single line. E.g., when the last character of a keyword is typed 
in a code editor and keywords are styled.

Any optimization would only apply to the non-bidi case since there is a special 
redrawBidiLines for bidi mode. redrawLines is called in internalRedrawRange 
which is called in setStyleRange.
Presently redrawLines does two calls to getXAtOffset if the start and end of 
the redrawRange is on the first line. This results in two GCs, two calls to 
getFontData and two calls to getLineStyleData.
The only way to avoid the duplicate calls is to fold the getXAtOffset/textWidth 
code into redrawLines. The resulting code would be very bloated and would have 
a lot of duplication. 
Creating a new getXAtOffset method that takes a GC, FontData and styles would 
not make this much nicer since a large part of the new code taken from 
getXAtOffset and textWidth deals with determining whether textWidth needs to be 
called at all and getting the styles if it does.
The performance increase would be about 18% but it is not clear how common this 
scenario is (using setStyleRange to set a style on a single line) and how 
critical better performance is. If you consider the character input creates 
keyword which gets styled then better performance is not critical (unless it is 
too slow now).
Comment 12 Knut Radloff CLA 2002-01-14 17:38:08 EST
Performance changes have long been released. Open new bug if new, specific 
performance problems surface.