Performance char vs string
Asked Answered
F

3

6

Just out of curiousity (not really expecting a measurable result) which of the following codes are better in case of performance?

private void ReplaceChar(ref string replaceMe) {
  if (replaceMe.Contains('a')) {
    replaceMe=replaceMe.Replace('a', 'b');
  }
}

private void ReplaceString(ref string replaceMe) {
  if (replaceMe.Contains("a")) {
    replaceMe=replaceMe.Replace("a", "b");
  }
}

In the first example I use char, while in the second using strings in Contains() and Replace()

Would the first one have better performance because of the less memory-consuming "char" or does the second perform better, because the compiler does not have to cast in this operation?

(Or is this all nonsense, cause the CLR generates the same code in both variations?)

Farl answered 20/4, 2016 at 8:22 Comment(6)
I think the recreation of the string is worse that the actual replacing.Greenhorn
Just guessing but would expect char version to perform better: no need to allocate strings, it is easier to search for a single character then for a group of characters (i.e. a string), Replace implementation knows the size of returned string in advance, so no need for potential additional allocations... But the only way to know is to measure.Desquamate
Isn't the if with Contains() unnecessary? Replace() will already check if it contains it.Reluctivity
Is it really that hard to write a compare loop yourself...Invigilate
@PeterB yes, writing performant compare/replace with string arguments in .NET is non-trivial, and why would anyone do it if there is a good implementation in framework?Desquamate
@PeterB As I wrote in Dmitris Answer: I wasn't expecting to get a siginificant difference above normal distribution.Farl
T
12

If you have two horses and want to know which is faster...

  String replaceMe = new String('a', 10000000) + 
                     new String('b', 10000000) + 
                     new String('a', 10000000);

  Stopwatch sw = new Stopwatch();

  sw.Start();

  // String replacement 
  if (replaceMe.Contains("a")) {
    replaceMe = replaceMe.Replace("a", "b");
  }

  // Char replacement
  //if (replaceMe.Contains('a')) {
  //  replaceMe = replaceMe.Replace('a', 'b');
  //}

  sw.Stop();

  Console.Write(sw.ElapsedMilliseconds);

I've got 60 ms for Char replacement and 500 ms for String one (Core i5 3.2GHz, 64-bit, .Net 4.6). So

 replaceMe = replaceMe.Replace('a', 'b')

is about 9 times faster

Trilateration answered 20/4, 2016 at 8:28 Comment(4)
Honestly I did not do a measurement, cause I was expecting the difference to be somewhere in a per mille region. good to know there really is a measurable difference. BTW: Having two horses run 1 million times would result in two dead horses most if the time :)Farl
worthy of note is that we're doing this on a string that is 30 MILLION chars long, and the "slow" version still only took less than a second. don't read too much into measurements like this unless you have actually determined for a fact and have concrete proof that this is a bottle-neck in your application. both are WAY more fast than "fast enough" for most imaginable applications.Censorship
@kai: you're quite right, but the question begins with "Just out of curiousity..." and I hope that the curiosity is satisfied ;)Trilateration
of course, I too can get quite intrigued by stuff like this, I just like to stress that in most cases, the answer is just that: a curiosity, of little practical value. I think it's a good answer within the scope of the question though!Censorship
G
1

We can't know for sure without testing the code since most of the replacing is done inside the CLR and it heavily optimized.

What we can say is this: replacing a char has some performance benefits since the code is simpler and the outcome is more predictable: replacing a char will always yield the same number of characters as the original for example.

In the performance of the replacing itself doesn't matter too much. In a tight loop, the allocation and garbage collection of the 'old' string will have a bigger impact than the replacement itself.

Greenhorn answered 20/4, 2016 at 8:29 Comment(0)
A
0

I've made a simple benchmark for anyone that will somehow end up here.

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19045

12th Gen Intel Core i7-12800H, 1 CPU, 20 logical and 14 physical cores .NET SDK=8.0.303

[Host] : .NET 8.0.7 (8.0.724.31311), X64 RyuJIT
DefaultJob : .NET 8.0.7 (8.0.724.31311), X64 RyuJIT

Method Mean Error StdDev
ReplaceChar 7.915 ns 0.1725 ns 0.1694 ns
ReplaceString 10.161 ns 0.2030 ns 0.1899 ns

Code:

    [Benchmark]
    public string ReplaceChar()
    {
        string replaceMe1 = "hello";

        replaceMe1.Replace('o', '0');

        return replaceMe1;
    }

    [Benchmark]
    public string ReplaceString()
    {
        string replaceMe2 = "hello";

        replaceMe2.Replace("o", "0");

        return replaceMe2;
    }
Astto answered 16/7 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.