A revisit to a tiny C# shortcut

My blog on string.IsNullOrEmpty() caused quite a stir (in my micro-scale, anyway), I got a number of comments, most of them interesting, and I feel happy of *not* being the only guy interested in silly small details. The feedback forced me to polish my benchmark, first of all James Bogosian is right: the performance differences are really small, I had to do 20'000.000 and 30'000.000 comparisons to see some stable differences. I also introduced the name.Length > 0 comparison out of several suggestions; after some cleaning, the results for the not null and not empty string tests were these:

.Length > 0 80 ms
string.IsNullOrEmpty() 110 ms
!= "" 270 ms
!= string.Empty 440 ms

And, surprise Edgar, name.Length > 0 is the best so Ramon Smits and other guys get a point here. The other  unexpected result is that comparing to string.Empty is a real bummer, so Darren Kopp suggestion is not really good (but he also supported the use of the Length property, so you're just OK, Darren). Someone suggested that comparing with "" is bad because a lot of string objects are generated, Ildasm shows that a ldstr "" instruction is generated just before the comparison, and although I'm far from an IL expert, I suspect no extra strings are being instantiated. Personally, I will stick to string.IsNullOrEmpty() because, as James pointed out, it's not only a matter of performance but of readability (or perhaps I am just rationalizing my bad habits ;-) ). You can download the test class from here, try it, mangle it, feedback me.

Published Monday, April 03, 2006 3:58 AM by Edgar Sánchez
Filed under:

Comments

# re: A revisit to a tiny C# shortcut

Monday, April 03, 2006 4:02 AM by foobar
I must say, the people that worked on the IL did a hell of a job.

# re: A revisit to a tiny C# shortcut

Monday, April 03, 2006 4:04 AM by foobar
Oh, do you have numbers for memory usage for each test?

# re: A revisit to a tiny C# shortcut

Monday, April 03, 2006 4:47 AM by Michael Schwarz
If you compare with null (what is missing in the first test with .Length) you will have the same result as string.IsNullOrEmpty(). Have a look on that static method you will find this:

public static bool IsNullOrEmpty(string value)
{
if (value != null)
{
return (value.Length == 0);
}
return true;
}

CIAO
Michael

# re: A revisit to a tiny C# shortcut

Monday, April 03, 2006 6:49 AM by Joe
The person who commented that comparing with "" generates a lot of string objects is wrong.

The String class has a so-called "intern pool" with one copy of each unique literal constant in a program. Each time you reference a literal including the literal "" for an empty string, you get back a reference to the *same* object from the intern pool.

# re: A revisit to a tiny C# shortcut

Monday, April 03, 2006 10:10 AM by Edgar Sánchez
Michael: He! That's a good one, so the extra time I see in my benchmark is probably due to the method call overhead. May be in a future version the compiler will inline the code and then we'll have both performance and readability. Come to think of it, may be there's already a compiler switch to do this, any takers?

# re: A revisit to a tiny C# shortcut

Monday, April 03, 2006 1:01 PM by foobar
Joe,

good to know. I was simply speculating on whether comparing to "" was good or bad.

# re: A revisit to a tiny C# shortcut

Monday, April 03, 2006 3:48 PM by Darren Kopp
Joe, notice that my comment about the "" creating a new string object had a question mark behind it, because I was only posing a hypothesis as to the slow down.

Edward,
I ran all of your code, and of course made some tweaks of my own. This is what i found out. I found that your findings were the same as mine, including my own code. As I began testing more, i did not bother with != "" or != string.Empty comparisons as they did not perform well at all.

The best performing condition is the following:

if (s != null && s.Length == 0)

which is basically just a rewrite of the isNullOrEmpty method, as michael stated (thank goodness for the reflector). here is the code i used to test it

start = DateTime.Now;
for (int l = 0; l < 10000000; l++)
{
switch (l % 3)
{
case 0:
isValid2 = (e != null && e.Length > 0);
break;
case 1:
isValid1 = (n != null && n.Length > 0);
break;
case 2:
isValid3 = (f != null && f.Length > 0);
break;
default:
break;
}
}
finish = DateTime.Now;
lapse = finish - start;

where e is "", n is null, and f is "Hello World!". I used the case on all other tests as well, to test variations (though predictable) of null, empty, or normal strings. This, I feel, will give a more rounded response time as some strings, like the null, will return much quicker than non-null strings.

I noticed that there was no difference between using .Length == 0 and .Length > 0, which isn't really surprising, but still worth testing.

In final, the statement i posted above consistently about 100 ms faster than calling the IsNullOrEmpty method, due to the overhead of calling a method (not to mention calling a method within a loop).

All in all, I agree that IsNullOrEmpty is the most readable and elegant, but if extreme performance is a requirement, then you may want to use the statement listed above.

Also worth mentioning is that I did rewrite the IsNullOrEmpty method's code within my own class, and tested that, and the results were identical with calling that one or string.IsNullOrEmpty.

# re: A revisit to a tiny C# shortcut

Monday, April 03, 2006 4:17 PM by Rodrigo Diniz
Correct me if I am wrong but you have to see if the string is null before trying to see the Length. If you try to get the Length of a null string you get an error.

# re: A revisit to a tiny C# shortcut

Tuesday, April 04, 2006 12:50 AM by John Walker
Wow, this is good info. I've been comparing using String.Empty in a lot of my code and I'm surprised it's slowest. In 2.0 I've been in the IsNullOrEmpty. Good info.

# re: A revisit to a tiny C# shortcut

Tuesday, April 04, 2006 2:00 AM by foobar
John, I wouldn't worry. Edgar had to run the tests 20-30 _million_ times to see appreciable differences (if you can call 440ms versus 80 ms "appreciable")

# re: A revisit to a tiny C# shortcut

Tuesday, April 04, 2006 3:28 AM by Joe
Were all the performance tests run with an app compiled in Release mode?

# re: A revisit to a tiny C# shortcut

Tuesday, April 04, 2006 3:47 AM by Edgar Sánchez
Joe: Yes, I used release mode for all my tests.

# re: A revisit to a tiny C# shortcut

Tuesday, April 04, 2006 10:26 AM by Bill McCarthy
I think you should be very careful when using String.IsNullOrEmpty as there are JIT optimisations with it that can cause null exceptions.
http://msmvps.com/blogs/bill/archive/2006/04/04/89234.aspx

# re: A revisit to a tiny C# shortcut

Tuesday, April 04, 2006 11:22 AM by Darren Kopp
I ran my tests in release mode as well. Debug mode results were fairly consistent to release mode, but took about 200 ms longer.

# re: A revisit to a tiny C# shortcut

Saturday, June 10, 2006 12:40 PM by comjwxe@hotmail.com
ringtones free

Leave a Comment

(required) 
(required) 
(optional)
(required)