FC18 Stay away from string.CompareTo

Culture based string comparison is slow

There are quite a few performance sink holes in .Net. The PerformanceCounter API we discussed before (FC03 Most PerformanceCounter usages are wrong (beehiiv.com)) is one of them. Another one is string.CompareTo. Here is its implementation:

It’s slow due to usage of CurrentCulture.CompareInfo, both getting it and its implementation are potential performance issues.

String implements IComparable interface, and this is its implementation. So you can get it every time your code is using the default string comparer. Here is a simple performance test:

The code is comparing the performance of sorting an array already sorted using default string comparer, which goes through string.CompareTo, and StringComparer.Ordinal. Here is the result:

StringComparer.Ordinal is 80% faster.

Here are CPU samples before (exclusive CPU samples):

Here are CPU samples after:

Here we can see StringComparer.Ordinal so much faster that even the overhead of Array.Sort is quite significant (the array is quite small).

string.CompareTo is mostly accessed through Comparer.Default. So it’s used by Array.Sort, List.Sort, SortedSet, SortedDictionary, with custom string comparer is not provided. Make sure add StringComparer.Ordinal when using them.

Using string.CompareTo is also semantically wrong, because ordering is based on current thread culture. If the same container is accessed from threads of different cultures, then you may not get the data you really want.

Stay away from string.CompareTo. In general, try to avoid culture related string comparers as much as possible.