Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Optimizing the Comparison of a Variable With Multiple Options in C#

DZone's Guide to

Optimizing the Comparison of a Variable With Multiple Options in C#

This article looks at optimizing comparison of variables for readability and performance, analyzing multiple types of object and array creation.

· Performance Zone
Free Resource

Yesterday, I wrote about my thoughts around optimizing the comparison of a variable with multiple options and how I prefer to optimize for readability over theoretical or potential performance issues. After some discussion on Twitter about how my sample code might be optimized I thought it was worth doing some proper analysis.

The big potential optimizations are

  • The removal of LINQ
  • Not creating a new array for each check
  • Removing the need for boxing
Using BenchmarkDotNet, I was able to quickly run some comparisons to see which method would be the quickest. I tried a number of variations with the type of object and array creation.

The results:

Method | Mean | Error | StdDev |
------------------------------------- |------------:|----------:|----------:|
MultipleEquals | 0.0013 ns | 0.0041 ns | 0.0034 ns |
IsOneOfObject | 132.7228 ns | 2.2074 ns | 2.0648 ns |
IsOneOfObjectWithExistingArray | 93.5959 ns | 1.7975 ns | 1.8459 ns |
IsOneOfGeneric | 63.4804 ns | 0.8762 ns | 0.7317 ns |
IsOneOfGenericWithExistingArray | 58.5615 ns | 0.8739 ns | 0.7747 ns |
IsOneOfMyEnum | 64.2691 ns | 1.3435 ns | 1.3195 ns |
IsOneOfMyEnumWithExistingArray | 58.2238 ns | 0.9457 ns | 0.8383 ns |
IsOneOfMyEnumNoLinq | 12.1887 ns | 0.2395 ns | 0.2123 ns |
IsOneOfMyEnumNoLinqWithExistingArray | 6.2302 ns | 0.0519 ns | 0.0433 ns |

Full benchmark code is at https://gist.github.com/mrlacey/1b3eef0a9945b67883486bb9540b533d.

While using multiple equality checks was by far the fastest approach, by removing LINQ, not boxing, and not creating a new array for each test I was able to achieve the best performance.

Conclusion

While using multiple equality checks is by far the fastest, I still think writing

if (MyEnum.Value1 || someVariable == MyEnum.Value2 || someVariable == MyEnum.Value3 || someVariable == MyEnum.Value6) { /// do something } 

is far less preferable to

if (someVariable.IsOneOf[MyEnumNoLinq](targetValues)) { /// do something }


And the code can still be pretty darn fast. You just might need a few overloads to get the best performance from all comparisons.

Disclaimer:

Yes, I am aware that:

  • I only ran the tests with enums and you might get different results with different types.
  • It might not be possible to have a fixed array to compare with each time.
  • There may be further optimizations available. This is good enough for me though.
  • Based on the speeds involved this does feel like a micro-optimization unless you really are making such calls many, many times in quick succession.
  • I haven't looked at memory usage. If you're interested, go ahead, but standard warnings about premature micro-optimizations exist.
*** UPDATE ***

Ok, I gave in and looked at the memory profiling too:

Method | Gen 0 | Allocated |
------------------------------------- |-------:|----------:|
MultipleEquals | - | 0 B |
IsOneOfObject | 0.0558 | 88 B |
IsOneOfObjectWithExistingArray | 0.0178 | 28 B |
IsOneOfGeneric | 0.0178 | 28 B |
IsOneOfGenericWithExistingArray | - | 0 B |
IsOneOfMyEnum | 0.0178 | 28 B |
IsOneOfMyEnumWithExistingArray | - | 0 B |
IsOneOfMyEnumNoLinq | 0.0178 | 28 B |
IsOneOfMyEnumNoLinqWithExistingArray | - | 0 B |

Yeah, I think it's safe to say that it's not an issue. If you're really concerned over 28 (or even 88) bytes you're in a really constrained environment and nothing I have to say about optimization or readability will be relevant or new to you. In fact, if you're in such a constrained environment you're probably best not writing in a managed language.

Topics:
performance ,c# ,performance optimization ,variables

Published at DZone with permission of Matt Lacey, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}