I'm trying to speed up the following:
string s; //--> s is never null
if (s.Length != 0)
{
<do something>
}
Problem is, it appears the .Length actually counts the characters in the string, and this is way more work than I need. Anybody have an idea on how to speed this up?
Or, is there a way to determine if s[0] exists, w/out checking the rest of the string?
EDIT: Now that you've provided some more context:
Trying to reproduce this, I failed to find a bottleneck in
string.Length
at all. The only way of making it faster was to comment out both the test and the body of the if block - which isn't really fair. Just commenting out the condition slowed things down, i.e. unconditionally copying the reference was slower than checking the condition.As has been pointed out, using the overload of
string.Split
which removes empty entries for you is the real killer optimization.You can go further, by avoiding creating a new char array with just a space in every time. You're always going to pass the same thing effectively, so why not take advantage of that?
Empty arrays are effectively immutable. You can optimize the null/empty case by always returning the same thing.
The optimized code becomes:
String.Length
absolutely does not count the letters in the string. The value is stored as a field - although I seem to remember that the top bit of that field is used to remember whether or not all characters are ASCII (or used to be, anyway) to enable other optimisations. So the property access may need to do a bitmask, but it'll still be O(1) and I'd expect the JIT to inline it, too. (It's implemented as anextern
, but hopefully that wouldn't affect the JIT in this case - I suspect it's a common enough operation to potentially have special support.)If you already know that the string isn't null, then your existing test of
is the best way to go if you're looking for raw performance IMO. Personally in most cases I'd write:
to make it clearer that we're not so much interested in the length as a value as whether or not this is the empty string. That will be slightly slower than the length test, but I believe it's clearer. As ever, I'd go for the clearest code until you have benchmark/profiling data to indicate that this really is a bottleneck. I know your question is explicitly about finding the most efficient test, but I thought I'd mention this anyway. Do you have evidence that this is a bottleneck?
EDIT: Just to give clearer reasons for my suggestion of not using
string.IsNullOrEmpty
: a call to that method suggests to me that the caller is explicitly trying to deal with the case where the variable is null, otherwise they wouldn't have mentioned it. If at this point of the code it counts as a bug if the variable is null, then you shouldn't be trying to handle it as a normal case.In this situation, the
Length
check is actually better in one way than the inequality test I've suggested: it acts as an implicit assertion that the variable isn't null. If you have a bug and it is null, the test will throw an exception and the bug will be detected early. If you use the equality test it will treat null as being different to the empty string, so it will go into your "if" statement's body. If you usestring.IsNullOrEmpty
it will treat null as being the same as empty, so it won't go into the block.Accessing the
Length
property shouldn't do a count -- .NET strings store a count inside the object.The SSCLI/Rotor source code contains an interesting comment which suggests that
String.Length
is (a) efficient and (b) magic:true if s is null or Empty, or if s consists exclusively of white-space characters.
Using the stopwatch the s.length != 0 takes less ticks then s == String.Empty
after I fix the code
Based on your intent described in your answer, why don't you just try using this built-in option on Split:
Here is the function String.IsNullOrEmpty -