Performance Hit for String.IsNullOrEmpty()?

K

Ken Wilson

In spite of the obvious advantage of not encountering a
NullReferenceException unexpectedly in your running program is there
an offset cost in performance for using String.IsNullOrEmpty() over !=
""? If so, would it be of any great significance if a large number of
strings were being tested over the run of an application?

Ken Wilson
Seeking viable employment in Victoria, BC
 
J

Jon Skeet [C# MVP]

Ken Wilson said:
In spite of the obvious advantage of not encountering a
NullReferenceException unexpectedly in your running program is there
an offset cost in performance for using String.IsNullOrEmpty() over !=
""? If so, would it be of any great significance if a large number of
strings were being tested over the run of an application?

Performance should always be secondary to correct behaviour. If a
string can be null and that needs to be checked, you should use
IsNullOrEmpty (or the manual pair of checks on 1.1). If you don't need
to check for null, just use != "". As the behaviour is significantly
different, you shouldn't be worrying about the performance, IMO.
 
S

Søren Reinke

Jon Skeet said:
Performance should always be secondary to correct behaviour. If a
string can be null and that needs to be checked, you should use
IsNullOrEmpty (or the manual pair of checks on 1.1). If you don't need
to check for null, just use != "". As the behaviour is significantly
different, you shouldn't be worrying about the performance, IMO.

I have a little side question.

What has best performance:

String helloString="hello";
if(myString==helloString)
{
}

or

String helloString="hello";
if(myString.equals(helloString))
{
}

Best regards
Søren Reinke
 
J

Jon Skeet [C# MVP]

Søren Reinke said:
I have a little side question.

What has best performance:

String helloString="hello";
if(myString==helloString)
{
}

or

String helloString="hello";
if(myString.equals(helloString))
{
}

(I assume you meant to write .Equals, not .equals.)

Well, again the semantics are different - the second will throw an
exception if myString is null, the first won't.

The performance of the second is *slightly* better when the strings are
short - as the strings increase in length, that difference becomes
completely insignificant. I'd be very surprised to find a real app
where the difference is *ever* significant.

However, the readability difference *is* significant, I believe - I
think the first version is much more readable (when you don't mind the
difference in semantics, eg because you know that myString is
non-null). Readability is almost always more important than
performance.

Jon
 
L

Ludovic SOEUR

I did some profiling assuming s1 is not null, because I thought it was
exactly the same.
You were right Jon and I don't understand why s1==s2 is slower than
s1.Equals(s2), and much slower when the strings are short.

Do you know why it can reach 75% of the speed ?

Whatever is the answer, s1==s2 is more readable and you dont have to check
if s1 is null.



"Jon Skeet [C# MVP]" <[email protected]> a écrit dans le message de
Søren Reinke said:
I have a little side question.

What has best performance:

String helloString="hello";
if(myString==helloString)
{
}

or

String helloString="hello";
if(myString.equals(helloString))
{
}

(I assume you meant to write .Equals, not .equals.)

Well, again the semantics are different - the second will throw an
exception if myString is null, the first won't.

The performance of the second is *slightly* better when the strings are
short - as the strings increase in length, that difference becomes
completely insignificant. I'd be very surprised to find a real app
where the difference is *ever* significant.

However, the readability difference *is* significant, I believe - I
think the first version is much more readable (when you don't mind the
difference in semantics, eg because you know that myString is
non-null). Readability is almost always more important than
performance.

Jon
 
J

Jon Skeet [C# MVP]

Ludovic said:
I did some profiling assuming s1 is not null, because I thought it was
exactly the same.
You were right Jon and I don't understand why s1==s2 is slower than
s1.Equals(s2), and much slower when the strings are short.

s1==s2 has to check for nullity in the operator.
s1.Equals(s2) make a virtual call, which makes the CLR generate code to
do the nullity check anyway. My guess is that that code is faster than
a straight "if (x==null)" kind of check. It's only a guess though.
Do you know why it can reach 75% of the speed ?

Whatever is the answer, s1==s2 is more readable and you dont have to check
if s1 is null.

Exactly - assuming that the behaviour you want is to get true when both
of them are null and false when s1 is null but s2 isn't, s1==s2 is the
best you can get, IMO.

Jon
 
L

Ludovic SOEUR

Jon Skeet said:
s1==s2 has to check for nullity in the operator.
s1.Equals(s2) make a virtual call, which makes the CLR generate code to
do the nullity check anyway. My guess is that that code is faster than
a straight "if (x==null)" kind of check. It's only a guess though.

I decompiled String class.

op_Equality(String, String) wich is what is called with s1==s2, this is the
code that is executed :
public static bool operator ==(string a, string b)
{
return string.Equals(a, b);
}

So let's have a look to String.Equals(string a, string b) :
public static bool Equals(string a, string b)
{
if ((object)a == (object)b) return true;
if ((a != null) && (b != null)) return a.Equals(b);
return false;
}

There is first a test that check if the two strings are the same object in
order not to do a useless comparison
Then, it calls s1.Equals(s2) only if none of s1 and s2 are null.

To conclude, s1==s2 make a call to a function that checks if the objects are
the same, then checks if none are null and then calls s1.Equals(s2);

That's why s1.Equals(s2) is "faster" than s1==s2.

To answer to Jon's guess, I decompiled a code with a 'null' check before
calling s1.Equals(s2);.....it's slower than the code in String.Equals(string
a, string b). Funny isn't it ? Maybe it's because it is not optimised by the
compiler. It doesn't keep in mind the addresses of s1 and s2 so it has to
"load" them twice in the registers.


Hope all of this helps,

Ludovic SOEUR.
 
K

Ken Wilson

Performance should always be secondary to correct behaviour. If a
string can be null and that needs to be checked, you should use
IsNullOrEmpty (or the manual pair of checks on 1.1). If you don't need
to check for null, just use != "". As the behaviour is significantly
different, you shouldn't be worrying about the performance, IMO.

Thanks for your reply. It makes perfect sense to use the appropriate
functionality for the situation you are expecting to deal with. I
imagine I can always do some timing tests should I run into a
situation where evaluating two strings is going to be a major part of
the task, given the caveat you've stated re: the possibility that null
strings may exist in the data being examined.

Ken Wilson
Seeking viable employment in Victoria, BC
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top