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