Have you heard of System.Text.StringBuilder? It is a .NET class which specializes in faster string manipulation. Can we use it in X++? Is it faster? How much faster? When is the break-even point on using the StringBuilder class? String concatenation (+) actually allocates, and populates a new variable in memory for the new string and then destroys the prior string. Strings are “immutable.”
We will create a stand-alone class in a brand new OneBox environment. First, let’s create a function to concatenate strings. The number of concatenations to perform and the size of the string will be parameters so several data points can be taken easily.
Then we’ll create a function to test the System.Text.StringBuilder class performance.
Now, we’ll bring it all together and make it runnable. Be sure to add a statement using System.Text at the top.
When executed, the class will output the test results to the infolog.
I used the above class, with varying calls to come up with the following table. You can test it yourself by downloading the code from my Github and navigating to https://usnconeboxax1aos.cloud.onebox.dynamics.com/?cmp=DAT&mi=SysClassRunner&cls=StringBuilderTester .
Executions | String Size | “Plus” Sign | StringBuilder |
---|---|---|---|
1,028 | 10 Characters | 984 Ticks | 0 Ticks |
20,560 | 10 Characters | 4,375 Ticks | 0 Ticks |
514,000 | 10 Characters | too long to wait | 125 Ticks |
10 | 100 Characters | 76 Ticks | 0 Ticks |
1,028 | 100 Characters | 94 Ticks | 0 Ticks |
20,560 | 100 Characters | 57,985 Ticks | 62 Ticks |
This was tested on a 10.0.0 PU24 OneBox running 6 vCPU at 2.8 GHz and 24 GB of RAM.
So it is clear that although we are not accustomed to it, using the StringBuilder class is a very good idea. Consider a long-running process that needs to build a large log. Consider using a StringBuilder to speed the process up!
Read more about when to use String or StringBuilder in the C# Docs.
Update May 2020
Mike Caterino expanded the logic for string::concat and strFmt as well (XML file). It clearly shows StringBuilder as the winner.
102800 concatenations of a 10-character string took 97750 ticks using String::Concat
102800 concatenations of a 10-character string took 443391 ticks using strFmt
102800 concatenations of a 10-character string took 44156 ticks using Plus symbol
102800 concatenations of a 10-character string took 0 ticks using StringBuilder
51400 concatenations of a 10-character string took 11172 ticks using String::Concat
51400 concatenations of a 10-character string took 54391 ticks using strFmt
51400 concatenations of a 10-character string took 29031 ticks using Plus symbol
51400 concatenations of a 10-character string took 0 ticks using StringBuilder
1028 concatenations of a 10-character string took 0 ticks using String::Concat
1028 concatenations of a 10-character string took 16 ticks using strFmt
1028 concatenations of a 10-character string took 15 ticks using Plus symbol
1028 concatenations of a 10-character string took 0 ticks using StringBuilder
102800 concatenations of a 10-character string took 113672 ticks using String::Concat
102800 concatenations of a 10-character string took 418156 ticks using strFmt
102800 concatenations of a 10-character string took 38219 ticks using Plus symbol
102800 concatenations of a 10-character string took 0 ticks using StringBuilder
51400 concatenations of a 10-character string took 9984 ticks using String::Concat
51400 concatenations of a 10-character string took 52016 ticks using strFmt
51400 concatenations of a 10-character string took 23640 ticks using Plus symbol
51400 concatenations of a 10-character string took 0 ticks using StringBuilder
1028 concatenations of a 10-character string took 16 ticks using String::Concat
1028 concatenations of a 10-character string took 16 ticks using strFmt
1028 concatenations of a 10-character string took 15 ticks using Plus symbol
1028 concatenations of a 10-character string took 0 ticks using StringBuilder
Summary-
1028000 concatenations of a 10-character string took 62 ticks using StringBuilder
514000 concatenations of a 10-character string took 16 ticks using StringBuilder
102800 concatenations of a 10-character string took 0 ticks using StringBuilder
51400 concatenations of a 10-character string took 0 ticks using StringBuilder
1028 concatenations of a 10-character string took 0 ticks using StringBuilder
Great post, Dag!