Right around the time that C# 3.0 came out, I was working on a project that required me to count the occurrences of a given character in a string. This was being done within a highly repetitive loop so it was imperative that it be as efficient as possible. I’ve always wanted to do performance testing on this and I finally got around to it recently and thought I’d post the results here.
There isn’t anything in the string class that gives us the functionality to count how many times an individual character occurs. I really hadn’t looked at Lambda expressions and someone at work suggested the following:
string testStr = "this,string,has,commas,in,it" ; int howMany = testStr.ToCharArray().Count(x => x == ',');
I thought, OK, nice and compact (all on one line) but I really didn’t understand it at the time and so went with a brute force way of doing it:
string testStr = "this,string,has,commas,in,it"; int howMany = 0 ; for (int j = 0; j < testStr.Length; ++j) { if (testStr[j] == ',') { ++howMany; } }
And I’m glad I did. Here’s why…
I’ve put up a test console application here. All this does is count the number of commas in a test string. It does this in 3 ways.
- using the Enumerable.Count() extension method
- using the Enumerable.Where().Count() extension methods
- using a straight for loop
The application is doing 250,000 iterations (e.g. – it’s counting the number of commas in the string 250,000 times for each method). The test string is “this,string,has,commas,in,it”.
Here is a typical output of that console application (times are in milliseconds).
We can see that doing a straight for loop is at least 2.5 times faster than the other methods.
A lot of stuff happens under the covers when using Lambda expressions which makes them very nice to use for clean, maintainable code, but they certainly aren’t the most efficient way of doing things sometimes.
If I had to write something similar today that was NOT in a really tight running loop, I’d definitely use a Lambda expression to simplify the code and make it cleaner. But for something that needs to be as efficient as possible, I’d definitely run some performance testing on it first to see how it performs.
