2

Which of the below is better in performance using LINQ?

sets.FirstOrDefault(x=>x.name=="xxx")

or

sets.FirstOrDefault(x=>!string.IsNullOrEmpty(x.name) && x.name.Equals("xxx",StringComparison.InvariantCultureIgnoreCase));

Here name can be null. I'm using this kind of query 20+ times in my app.

Is there any better approach?

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
malkam
  • 2,337
  • 1
  • 14
  • 17
  • Is this LINQ to Objects, or something else? Do you have any indication that this is your performance bottleneck? Have you *tried* both approaches? (Personally I'd go with the first just for the sake of readability, unless you've got any concrete evidence that the second is significantly faster.) – Jon Skeet Jun 04 '14 at 09:45
  • I don't see how the question has anything to do with LINQ. – dcastro Jun 04 '14 at 09:46
  • 1
    @user2864740 So what? The difference between the two code snippets is the string comparison. So the question should be: which of these two ways of comparing strings is faster? – dcastro Jun 04 '14 at 09:48
  • 1
    @dcastro Disagree. Firstly its comparing apples to oranges, one of them is going to be wrong no matter what, that one by definition NEVER returns the correct answer, thus, is slower. Second, since a Linq provider is not provided, neither code snippets are "complete", thus neither actually run. Thirdly certain Linq providers will actually fail to convert one or the other `Expresssion>`. Fourthly, some of those Linq providers actually will compile both Expressions to the same code. – Aron Jun 04 '14 at 09:52
  • @dcastro As Jon Skeet points out there is a difference depending on the provider of `sets`. Suppose `sets` is some database table, the first might be translated to a simple sql query, the second might not be able to and the whole table needs to be fetched potentially. – weston Jun 04 '14 at 09:53
  • sets is list of objects. Actually I'm using above linq query in extracting properties from soap req object in wcf which will be called ~200 per second and performance matters. – malkam Jun 04 '14 at 09:55
  • @malkam it is clear you actually haven't done any perf benchmarks. So I am going to break it down for you. Modern processor 4x 3GHz, able to do ~ 10^10 comparisons per second. 200 times per second is really nothing. Further more, if this is an app with a UI, the typical refresh rate on an LCD screen allows ~ 30 frames per second. There is likely no reason to ping 200 times per second. Finally, with network jitter, 200 times per second is actually pretty problematic. – Aron Jun 04 '14 at 10:00

3 Answers3

6

There is a major difference between the two statements, so you just can't only judge them on performance.

The first one performs better, but the second one will give different results (since it doesn't check on upper/lower case and diacritics).

Optionally, you could rewrite the second like this:

sets.FirstOrDefault(x => string.Equals(x.name, "xxx",StringComparison.OrdinalIgnoreCase));

It doesn't need the string.IsNullOrEmpty which will make the second call a little faster than it was.

As noted by weston: The use of OrdinalIgnoreCase performs better then InvariantCultureIgnoreCase, hence this notice of Microsoft.

Community
  • 1
  • 1
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • Please remove ! in condition. I'll mark it as answer – malkam Jun 04 '14 at 09:57
  • Another speed improvement (in theory) is use of `StringComparison.OrdinalIgnoreCase` http://msdn.microsoft.com/en-us/library/ms973919.aspx http://stackoverflow.com/a/2256491/360211 – weston Jun 04 '14 at 10:09
0

If you're only running this ~20 times, it wont matter too much, but the first option will be faster because the second does an additional null check.

Philip Pittle
  • 11,821
  • 8
  • 59
  • 123
0

I have not tested it, but I'd bet sets.FirstOrDefault(x=>x.name=="xxx") is faster. Simple reason - it does less work, and less work is faster.

Although, this type of performance improvements are usually not worth it. You'll gain much more performance benefits by looking at the architecture of your app.

kevin
  • 2,196
  • 1
  • 20
  • 24
  • 2
    How can you know that it does less work if you haven't tested it? – default Jun 04 '14 at 09:53
  • If anything, due to how the ASCII char set is setup, it is possible that `InvariantCultureIgnoreCase` will make 1 less bit comparison per char. Secondly, assuming Linq2Object, the first one could never return (throw) due to a null exception. – Aron Jun 04 '14 at 09:56
  • @weston its less work, but doesn't mean faster. Could depend on hardware of course... However the main take away is...don't assume with perf, modern computers have so many layers of optimisation you actual don't know what is running on your CPU (and that is a good thing). – Aron Jun 04 '14 at 10:03
  • @Aron It's not less work as processors don't work bit-by-bit. So they must still do the whole comparison then apply a mask to ignore bits they don't care about. So case insensitive comparison is more work. – weston Jun 04 '14 at 10:05
  • @weston A better argument is that we are actually working in UTF-8 (you should read Think of the Ponies by Jon Skeet). But the main point I want to put across is that at this level it is heavily implementation dependent, and in fact that is a good thing. The modern programmer really should not be thinking about such things. – Aron Jun 04 '14 at 10:13
  • @Aron I agree, but you were the one who brought up bits and ASCII. – weston Jun 04 '14 at 10:20