Community
Participate
Working Groups
PR to keep track of performance issues, solutions, etc. on the bidi platform.
Changed StyledText.getBidiSegmentsCompatibility to return immediately when bidiColoring is false. It used to always call getLineStyleData.
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.
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.
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.
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).
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.
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.
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%.
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.
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)
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).
Performance changes have long been released. Open new bug if new, specific performance problems surface.