Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Concatenating strings speed test - which is faster

Discussion in 'Scripting' started by Maccyfin, Jul 3, 2020.

  1. Maccyfin

    Maccyfin

    Joined:
    Aug 19, 2012
    Posts:
    87
    Hey all. Today I looked into which string concatenate method works best in regards to speed. The methods I tested were:

    - String + operator: string1 + string 2;
    - String interpolation: $"{string1}{string2};
    - String.Concat(): string.Concat(string1, string2);
    - String format: System.String.Format("{0}{1}", string1, string2);

    RESULTS



    SPEED (fastest at the top)

    1) String.Concat()
    2) String + operator
    3) String interpolation
    4) System.String.Format


    CODE
    Here's the full code I tested along with the timer methods:
    Code (csharp):
    1.  
    2.     public float StringPlusOperatorTest()
    3.     {
    4.         Stopwatch stopwatch = new Stopwatch();
    5.         stopwatch.Start();
    6.         string sWord1 = "One";
    7.         string sWord2 = "Two";
    8.         string sWords = sWord1 + sWord2;
    9.         stopwatch.Stop();
    10.         return (float)stopwatch.Elapsed.TotalMilliseconds;
    11.     }
    12.     public float StringInterpolationTest()
    13.     {
    14.         Stopwatch stopwatch = new Stopwatch();
    15.         stopwatch.Start();
    16.         string sWord1 = "One";
    17.         string sWord2 = "Two";
    18.         string sWords = $"{sWord1}{sWord2}";
    19.         stopwatch.Stop();
    20.         return (float)stopwatch.Elapsed.TotalMilliseconds;
    21.     }
    22.     public float StringDotConcatTest()
    23.     {
    24.         Stopwatch stopwatch = new Stopwatch();
    25.         stopwatch.Start();
    26.         string sWord1 = "One";
    27.         string sWord2 = "Two";
    28.         string sWords = string.Concat(sWord1, sWord2);
    29.         stopwatch.Stop();
    30.         return (float)stopwatch.Elapsed.TotalMilliseconds;
    31.     }
    32.     public float StringDotFormatTest()
    33.     {
    34.         Stopwatch stopwatch = new Stopwatch();
    35.         stopwatch.Start();
    36.         string sWord1 = "One";
    37.         string sWord2 = "Two";
    38.         string sWords = System.String.Format("{0}{1}", sWord1, sWord2);
    39.         stopwatch.Stop();
    40.         return (float)stopwatch.Elapsed.TotalMilliseconds;
    41.     }
    42.  
    NOTES / CONCLUSION

    Based on the results above it would seem that the difference between the + operator, string interpolation and string.Concat() is very small and probably won't make that much difference in a full game code base. However String.Format takes three times as much time as string interpolation.

    The results above also don't take into account garbage collection and its impact on the test. After speaking with some of the other forum members, it's something I need to take into account when doing these benchmarks.

    Any feedback as always is great guys. I hope these are useful, or interesting at the least.

    Happy Developing
    Martin
     
  2. Maccyfin

    Maccyfin

    Joined:
    Aug 19, 2012
    Posts:
    87
    To add a point on the GC (Garbage Collection) front. It also looks like each of the 4 methods have the same amount of memory allocated. And so no memory benefit of using one above the other.



    By the way, does anyone know if we can get the GC Alloc value via script for a specific chunk of code?
     
    Last edited: Jul 3, 2020
  3. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,516
    I believe StringBuilder is the way to go for performance if you need to manipulate strings a lot. It'd be a good idea to add that to your test.

    Note that the Format() method really isn't comparable. You can use it to combine stuff, but its purpose is formatting them, which is why it does a lot of extra work, which you're not taking advantage of here.

    Also note that looking at the higher level approach could be handy here, once again. For instance, often in games we can keep string manipulation to a minimum by just not combining strings before using them. An example is instead of using a label that says "Health: 46" and recreating that string every time the number changes, have two labels and only update the number part. Same visual result, fewer string operations.

    Edit: A question... why are you posting these in General Discussion instead of Scripting?
     
    lordofduct likes this.
  4. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,931
    Also, if one uses the Unity UI, it should be this way. The "health" label should be part of a canvas which never (or rarely changes) and the number should be part of a canvas which may changes more frequently in order to only update only the changing UI parts, not the entire UI hierarchy all the time.
     
  5. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,448
    Alternatively or additionally use TextMeshPro.SetText for your UI label to avoid gcalloc's caused by string manipulation altogether.
     
    LuckyMisterSleven and rodrycode like this.
  6. Maccyfin

    Maccyfin

    Joined:
    Aug 19, 2012
    Posts:
    87
    Hey guys, thanks for the reply and tips.

    Good point, I'll give it a whirl and add results here.

    I'd read about this optimization, its a good tip for sure.
    It's now been moved to scripting. Any future ones I'll put in 'scripting' too.

    This is interesting. I didn't know that updating a single text item updates the entire hierarchy, Im definitely gonna test this one out.

    I never knew this. Gonna try it out as well, great tip :)
     
  7. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,833
    I wouldn't expect StringBuilder to help if you are concatenating exactly 2 things and they are already both strings. My understanding is that it's meant to avoid the repeated memory allocations caused by repeated concatenations, or by converting non-string objects into strings so that they can be concatenated.

    But I haven't tested.
     
  8. Maccyfin

    Maccyfin

    Joined:
    Aug 19, 2012
    Posts:
    87
    I need to test these methods with non-strings too.
     
  9. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,120
    I don't know whether it would matter, but I'd recommend doing this in a build too, rather than just in the editor. Maybe for something like this it doesn't matter, but it would be good to confirm that.
     
    Peter77 likes this.
  10. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,931
    If you care about performance, you _must_ watch this.

     
    Peter77 likes this.
  11. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,516
    The important thing is that in C# strings are immutable. Their contents can not be changed after creation, so when you perform operations on strings it actually creates a whole new string object. The benefit of a StringBuilder is that it is mutable, so its contents can be changed without creating a whole other object as a result.

    You're right that using it for trivial cases is unlikely to be helpful, because you still need to create the StringBuilder in the first place.

    Definitely helpful. Depending on what you're doing remember that C# calls ToString() on stuff to get its string representation, so there may be allocations even if they're not from within the SetText() method itself.
     
  12. Maccyfin

    Maccyfin

    Joined:
    Aug 19, 2012
    Posts:
    87