Faculty of Information Technology
Software Engineering Group

Opened 2 years ago

Last modified 13 months ago

#138 new defect

Unicode32String is really really slow when scrolling the text

Reported by: Patrik Svestka Owned by:
Priority: major Milestone:
Component: default Keywords:
Cc: Also affects CVS HEAD (eXept version): no

Description

I have observed that the Unicode32String is really really slow compared to the String or Unicode16String. Of course, Unicode32String can be somewhat slower as it contains more but current situation is, in my opinion, way too much.

Second thing more serious but for which I don't have any proof yet. When the Unicode32String is running for long time (rendering the text) during which it uses 1 core of the multi-core CPU (due to the VM nature of StX) to the 100%, it corrupts memory - I left it running for more than 10 minutes and after like 8 minutes my opened browser (I had only one tab opened) started to behave really weird - the normal keys started to opened different tabs, configuration; to me this behavior is similar to memory corruption. You can try to leave the below code running for long time and you will see if this can be reproduced.

The following code has String, Unicode16String, Unicode32String (uncomment the String comment block you want to run):

maxCharBuffer := 10000. 
charToDisplay := 100000.

"/String
"contents := String new: charToDisplay.
tempContents := String new."
"/Unicode16String
"contents := Unicode16String new: charToDisplay.
tempContents := Unicode16String new."
"/Unicode32String
contents := Unicode32String new: charToDisplay.
tempContents := Unicode32String new.

aLetterCollection := OrderedCollection new.
startingLetter := $A.

iterrations := (charToDisplay / maxCharBuffer).

iterrations isInteger ifFalse:[ 
                        iterrations := (iterrations asFloat) floor + 1.
                      ].

(1 to: iterrations) do: [:aNumber |
                      aLetterCollection add: (((startingLetter asInteger - 1) + aNumber) asCharacter).
                    ].

aLetterCollection do: [:aLetter|
  charToDisplay > maxCharBuffer ifTrue: [
      pickContents := contents copyFrom:1 to:maxCharBuffer.
      pickContents replaceAll: Character space with: aLetter.
      tempContents := tempContents, pickContents.
      contents := contents copyFrom:(maxCharBuffer+1) to:charToDisplay.  
      charToDisplay := charToDisplay - maxCharBuffer.
      "/pickContents inspect.
     "/tempContents inspect.
    ] ifFalse: [
        remainingContents := contents copyFrom:1 to:charToDisplay.
        remainingContents replaceAll: Character space with: aLetter.
        contents := tempContents, remainingContents.
       ].
  ].

top := StandardSystemView new.
top extent:300@200.

textView := EditTextView new.
textView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
top addSubView:textView.

textView contents: contents.

top open.

Attachments (2)

Unicode32String_slow.mp4 (1.2 MB) - added by Patrik Svestka 2 years ago.
Showing comparison of String, Unicode16String, Unicode32String
WinWorkstation-widthOf:from:to:inFont:.st (1.4 KB) - added by Jan Vrany 2 years ago.

Download all attachments as: .zip

Change History (5)

Changed 2 years ago by Patrik Svestka

Attachment: Unicode32String_slow.mp4 added

Showing comparison of String, Unicode16String, Unicode32String

comment:1 Changed 2 years ago by Patrik Svestka

Summary: Unicode32String is really really slowUnicode32String is really really slow when scrolling the text

Changed 2 years ago by Jan Vrany

comment:2 Changed 2 years ago by Jan Vrany

One problem is that edit text view needs to compute a width of a sub-string in order to determine pixel-position of a cursor. The string is in this case Unicode32String and as such cannot be passed to Window's GetTextExtentPoint32W() as it takes only UTF16 strings.

So, in order to compute the width, original string have to be converted to UTF16 string. Current code converts whole original string, which takes very long. By more careful coding
(see attached change) one can reduce the conversion to what is actually needed.

Still, in provided testcase this conversion takes a lot of a time so we may need to optimize more:

  • We may optimize Unicode16String >> copyFrom:to:with:startingAt: and special-case it for copying from Unicode32String - and possibly manually unroll the loop (but remember, we have to bail-out iff the character in source does not fit into 16bit range)
  • We may do the conversion directly in WinWorkstation>>widthOf:from:to:inFont:in:with: into some static and/or quick-allocated buffer and then use GetTextExtentPoint32W().

Further optimization may be done at higher-level in EditTextView itself, though this would be the thougest and I'd resort to that after implementing all of the above.

Last edited 2 years ago by Jan Vrany (previous) (diff)

comment:3 Changed 13 months ago by Patrik Svestka

Apparently the textView is slow even when using just Unicode16String.

You can test it on the following example:

testString := Unicode16String new.
testString := 'コーヒーアイスクリームケーキビールすしかき'.

top := StandardSystemView new.
top extent:300@200.

textView := EditTextView new.
textView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
top addSubView:textView.
1 to: 1000 do: [ :each | textView paste:testString ].

top open.
Note: See TracTickets for help on using tickets.