This post might seem weird and is slightly. It's really just a pointer as with all my posts to send people to instead of sharing lots of text "on the down low" .
So this all started because we have a utility lib with lots of the common string extensions like ToInt32
, ToDateTime
, etc. in it and one of the methods is IsBoolean
. I decided for the hell of it that I'm going to wrap all the utilities that we have in unit tests. Most of these are really old, from a time when writing tests was a waste of time. During this process, I wanted to make sure we had the tests documenting sort of the things that we supported as well and where the boundaries are of what is supported as we use standard .NET methods, but then also our own logic for defining things like in this case IsBoolean
. The rabbit hole today started with Pressing F12 on bool.TryParse which because I have the ref F12 extension installed took me straight to the source definition to understand what .NET is doing under the covers to know its boundaries.
Discovery 1
The first discovery I made which makes sense, but I didn't really think of it before is that .NET will check for whitespaces for you.
More Rambling
There have been plenty of occasions where I have been faced with the problem of "I can optimize that more" and then realized that there isn't really any point in optimizing something that's rarely called for a couple of milliseconds. When I see this code (being the .NET Framework), there is every little opportunity to optimize even in something like a TryParse
method which is probably quite core to many other functions in the framework and other systems. The framework basically repeats the same code saying it's going to do a check first ignoring whitespace.
and you think to yourself is that really going to do much?
Discovery 2
I often wonder about small things like would testing for to upper case or to lower case be faster than the other, maybe a bad example, but you get the point (I hope). In this case, something that long ago I wondered which is what is faster, testing True
is True
faster or False
is False
faster .
From this test, it appears because of the order of the code that testing for True
is faster than testing for False
, obviously null
being checked is still faster. Which makes me wonder if adding a test to check value.Length < 4
return false
would add enough performance gain to warrant being added in. In thinking about that, I recon if it was thought about, it would have been removed as an idea because that would be optimizing for the (hopefully) least used scenario.
The Test Results
So I used BenchmarkDotNet for my speed tests and below are my findings, the code is super simple to test this one which you can find out on my GitHub Gists.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace TestingIsBoolean
{
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<Tests>();
}
}
public class Tests
{
[Benchmark]
public bool Null()
{
return IsBool(null);
}
[Benchmark]
public bool False()
{
return IsBool("False");
}
[Benchmark]
public bool True()
{
return IsBool("True");
}
[Benchmark]
public bool FalseWithWhitespace()
{
return IsBool("False ");
}
[Benchmark]
public bool TrueWithWhitespace()
{
return IsBool("True ");
}
private static bool IsBool(string input)
{
return bool.TryParse(input, out bool obj);
}
}
}
And after running a couple times just to 100% make sure this is the kind of results I get:
Interesting? I think so.
Conclusion
I think although this is a small case, it highlights the importance of knowing and understanding what the .NET framework is doing for you. I have seen a couple of code samples and code in live systems that perform a trim on a string
before doing the try parse for example when in their case that are doing the whitespace trim work each call of the function where it would be taking care of for them automatically by the framework.