Reduce allocations in string.ToLower/ToUpper on Unix
authorstephentoub <stoub@microsoft.com>
Thu, 8 Oct 2015 15:51:14 +0000 (11:51 -0400)
committerstephentoub <stoub@microsoft.com>
Thu, 8 Oct 2015 15:51:14 +0000 (11:51 -0400)
On Windows, ToLower/ToUpper calls into InternalChangeCaseString in the runtime which does two optiizations:
- a 0-length check to just return an empty string if the source is empty
- allocates the string and writes the results into it directly

In our current Unix implementation, the ChangeCase implementation doesn't do either of these, no special-casing empty strings and first allocating a char[] into which the results are written and then constructing a string from that.

This commit brings the Unix implementation more in line with the Windows one, adding the 0-length check, and writing the results directly into the result string so as to avoid the unnecessary char[] allocation and copy.

src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs

index 9a64917..0d7003f 100644 (file)
@@ -30,27 +30,28 @@ namespace System.Globalization
         {
             Contract.Assert(s != null);
 
-            char[] buf = new char[s.Length];
+            if (s.Length == 0)
+            {
+                return string.Empty;
+            }
 
-            fixed(char* pBuf = buf)
+            string result = string.FastAllocateString(s.Length);
+            fixed (char* pBuf = result)
             {
-                Interop.GlobalizationInterop.ChangeCase(s, s.Length, pBuf, buf.Length, toUpper, m_needsTurkishCasing);
+                Interop.GlobalizationInterop.ChangeCase(s, s.Length, pBuf, result.Length, toUpper, m_needsTurkishCasing);
             }
 
-            return new string(buf);
+            return result;
         }
 
         [System.Security.SecuritySafeCritical]
         private unsafe char ChangeCase(char c, bool toUpper)
         {
-            char* pSrc = stackalloc char[1];
-            char* pDst = stackalloc char[1];
-
-            pSrc[0] = c;
+            char dst = default(char);
 
-            Interop.GlobalizationInterop.ChangeCase(pSrc, 1, pDst, 1, toUpper, m_needsTurkishCasing);
+            Interop.GlobalizationInterop.ChangeCase(&c, 1, &dst, 1, toUpper, m_needsTurkishCasing);
 
-            return pDst[0];
+            return dst;
         }
 
         // -----------------------------