Improved text handling in TextFieldPlus
This past week, I wrote a post regarding the sluggish TextField.text method. I also shared an alternative that shows incredible gains—storing the text prior to modifying it. I originally found it was 11 times faster, but after redoing the tests, I discovered that TextField.text‘s speed is dependent on the number of characters in the String. Here are the results, including the new TextFieldPlus.text:
1 lorem ipsum paragraph (584 characters) var text...........................42 / 0.071 msec/char (100,000 iterations) TextFieldPlus.text.................63 / 0.107 msec/char (100,000 iterations) TextField.text....................458 / 0.784 msec/char (100,000 iterations) 2 lorem ipsum paragraph (1,168 characters) var text..........................42 / 0.035 msec/char (100,000 iterations) TextFieldPlus.text................64 / 0.054 msec/char (100,000 iterations) TextField.text...................1098 / 0.94 msec/char (100,000 iterations) 3 lorem ipsum paragraph (1,752 characters) var text..........................42 / 0.023 msec/char (100,000 iterations) TextFieldPlus.text................64 / 0.036 msec/char (100,000 iterations) TextField.text..................2379 / 1.357 msec/char (100,000 iterations)
As you can see, the pre-stored method and TextFieldPlus.text maintain the same speed as the String grows, but TextField.text slows. TextFieldPlus.text uses the pre-stored method, but isn’t as fast because it’s a getter and includes a conditional to play nice with htmlText. Even so, the less work for the developer is worth the extra 20 milliseconds.
Along with TextField.text, I tackled TextField.text += String. This is even slower because it requires both getting and setting. It’s so slow, in fact, that the debugger displays a warning and suggests using TextField.append instead. This is considerably faster, but still slow.
To combat the speed issues, I developed a transaction-based system, inspired the SQLConnection class. With beginText and commitText, you can batch-modify a TextField‘s text with either += or appendText. The latter is still faster, but by a slighter margin. Here are the speed results:
1,000 iterations var text +=...............................................................1 TextField.text +=.......................................................620 TextField.append........................................................583 TextFieldPlus.text +=...................................................571 TextFieldPlus.appendText................................................578 TextFieldPlus.text += (transaction).......................................2 TextFieldPlus.appendText (transaction)....................................1 100,000 iterations var text +=..............................................................53 TextField.text +=.................................................timed out TextField.append..................................................timed out TextFieldPlus.text +=.............................................timed out TextFieldPlus.appendText..........................................timed out TextFieldPlus.text += (transaction).....................................116 TextFieldPlus.appendText (transaction)...................................93
Just as before, TextFieldPlus‘s methods are slightly slower, but the difference is worth it from a developer’s standpoint. While writing the new appendText method, I discovered a fun fact about TextField.appendText—the method actually calls TextField.replaceText(TextField.length, TextField.length, text). With this new knowledge, I figured I’d skip the middleman and call super.replaceText from appendText. Surprisingly, this is slower, so I stuck with super.appendText.
The updated source code is on GitHub, so TextFieldPlus is ready to go with the new implementation.
Last post I thought it was ridiculous that TextField.text was slower than making the getter yourself. I don’t even know what to say about TextField.text performing in any time other than O(1). How can it take longer when there is more text? It scales up so fast that it’s not even linear. I computed these from your numbers:
584 characters: 0.78 ms/character
1168 characters: 0.94 ms/character
1752 characters: 1.35 ms/character
It’s truly sad. Good thing we have your TextFieldPlus! Thanks Jonnie!
@Jackson — You learn something new every day! I’m pretty thrilled to have stumbled across these findings, and hopefully I find more as I continue the framework. I’m wondering what to tackle next