6

I read in CLR via C# by Jeffrey Richter that String.ToUpperInvariant() is faster than String.ToLowerInvariant(). He says that this is because the FCL uses ToUpperInvariant to normalise strings, so the method is ultra-optimised. Running a couple quick tests on my machine, I concur that ToUpperInvariant() is indeed slightly faster.

My question is if anybody knows how the function is actually optimised on a technical level, and/or why the same optimisations were not applied to ToLowerInvariant() as well.


Concerning the "duplicate": The proposed "duplicate" question really doesn't provide an answer to my question. I understand the benefits of using ToUpperInvariant instead of ToLowerInvariant, but what I would like to know is how/why ToUpperInvariant performs better. This point is not addressed in the "duplicate".

Levi Botelho
  • 24,626
  • 5
  • 61
  • 96
  • Looks like the job for your friendly ildasm or favorite decompiler. – Dustin Kingen Sep 06 '13 at 12:28
  • 1
    http://stackoverflow.com/questions/2801508/what-is-wrong-with-tolowerinvariant – Dennisch Sep 06 '13 at 12:28
  • Both `ToUpperInvariant()` and `ToLowerInvariant()` end up calling `InternalChangeCaseString()`, so the magic must be some optimizations within (or in methods called by) that method. – Matthew Watson Sep 06 '13 at 12:35
  • @MatthewWatson, Romuku - Effectively when looking with the ReSharper decompiler InternalChangeCaseString is called, which is interesting because I suspected that both methods might end up calling some shared function. However because InternalChangeCaseString is implemented directly in the CLR, I guess there's not much hope of knowing exactly what optimisations they put in place which leads to this behaviour. – Levi Botelho Sep 06 '13 at 12:43
  • 1
    Maybe this is also of interest: http://stackoverflow.com/questions/297703/how-do-you-set-strings-to-uppercase-lowercase-in-unicode – Corak Sep 06 '13 at 12:47
  • What about [this answer](http://stackoverflow.com/questions/2801508/what-is-wrong-with-tolowerinvariant/2801656#2801656)? – Ferdinand.kraft Sep 07 '13 at 13:50
  • Already referenced in the second comment ;). It doesn't explain how the optimisation is functionally done, which is what I'm interested in, and particularly why the optimisation was not applied to `ToLowerInvariant`. I'm starting to think that the only person who can answer this is with this level of detail is someone like @EricLippert who actually has an in-depth knowledge of the CLR. – Levi Botelho Sep 07 '13 at 17:18
  • They both go back to `InternalChangeCaseString()`. This is where you could dig deeper. – Jibbow Apr 15 '15 at 11:42

1 Answers1

3

Since it is now easier to read the CLR source which implements InternalChangeCaseString, we can see that it mostly calls down to the Win32 function LCMapStringEx. There appears to be no notes or any discussion on the performance of passing in LCMAP_UPPERCASE vs. LCMAP_LOWERCASE for the dwMapFlags parameter. Calling InternalChangeCaseString uses a flag isToUpper which, if true may result in better optimization by the compiler (or JITter), but since the call to LCMapStringEx has to setup a p/invoke call frame and the call itself has to do work, I'm not sure a lot of time is saved there.

Perhaps the recommendation is a hold over from some other implementation, but I can't see anything that would provide a significant speed advantage one way or the other.

codekaizen
  • 26,990
  • 7
  • 84
  • 140