Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 38cf930

Browse files
authored
Cache Invariant CompareInfo (#15902)
The Invariant CompareInfo is used in number of places. It is fetched via virtual method on CultureInfo. Caching it avoids the virtual method calls and extra indirections.
1 parent 7718dec commit 38cf930

File tree

7 files changed

+34
-59
lines changed

7 files changed

+34
-59
lines changed

src/mscorlib/shared/System/Globalization/CompareInfo.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public partial class CompareInfo : IDeserializationCallback
5757
~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
5858
CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort);
5959

60+
// Cache the invariant CompareInfo
61+
internal static readonly CompareInfo Invariant = CultureInfo.InvariantCulture.CompareInfo;
62+
6063
//
6164
// CompareInfos have an interesting identity. They are attached to the locale that created them,
6265
// ie: en-US would have an en-US sort. For haw-US (custom), then we serialize it as haw-US.

src/mscorlib/shared/System/Globalization/DateTimeFormatInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ public int GetEra(String eraName)
593593
{
594594
// this comparison should use the InvariantCulture. The English name could have linguistically
595595
// interesting characters.
596-
if (CultureInfo.InvariantCulture.CompareInfo.Compare(eraName, m_abbrevEnglishEraNames[i], CompareOptions.IgnoreCase) == 0)
596+
if (CompareInfo.Invariant.Compare(eraName, m_abbrevEnglishEraNames[i], CompareOptions.IgnoreCase) == 0)
597597
{
598598
return (i + 1);
599599
}

src/mscorlib/shared/System/Globalization/TextInfo.cs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,28 +91,6 @@ internal static int GetHashCodeOrdinalIgnoreCase(string s)
9191
return Invariant.GetCaseInsensitiveHashCode(s);
9292
}
9393

94-
// Currently we don't have native functions to do this, so we do it the hard way
95-
internal static int IndexOfStringOrdinalIgnoreCase(string source, string value, int startIndex, int count)
96-
{
97-
if (count > source.Length || count < 0 || startIndex < 0 || startIndex > source.Length - count)
98-
{
99-
return -1;
100-
}
101-
102-
return CultureInfo.InvariantCulture.CompareInfo.IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
103-
}
104-
105-
// Currently we don't have native functions to do this, so we do it the hard way
106-
internal static int LastIndexOfStringOrdinalIgnoreCase(string source, string value, int startIndex, int count)
107-
{
108-
if (count > source.Length || count < 0 || startIndex < 0 || startIndex > source.Length - 1 || (startIndex - count + 1 < 0))
109-
{
110-
return -1;
111-
}
112-
113-
return CultureInfo.InvariantCulture.CompareInfo.LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
114-
}
115-
11694
public virtual int ANSICodePage => _cultureData.IDEFAULTANSICODEPAGE;
11795

11896
public virtual int OEMCodePage => _cultureData.IDEFAULTOEMCODEPAGE;

src/mscorlib/shared/System/String.Searching.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,16 @@ public int IndexOf(char value, StringComparison comparisonType)
5353
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, CompareOptions.IgnoreCase);
5454

5555
case StringComparison.InvariantCulture:
56-
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, CompareOptions.None);
56+
return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.None);
5757

5858
case StringComparison.InvariantCultureIgnoreCase:
59-
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, CompareOptions.IgnoreCase);
59+
return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.IgnoreCase);
6060

6161
case StringComparison.Ordinal:
62-
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, CompareOptions.Ordinal);
62+
return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.Ordinal);
6363

6464
case StringComparison.OrdinalIgnoreCase:
65-
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, CompareOptions.OrdinalIgnoreCase);
65+
return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.OrdinalIgnoreCase);
6666

6767
default:
6868
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
@@ -361,16 +361,16 @@ public int IndexOf(String value, int startIndex, int count, StringComparison com
361361
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
362362

363363
case StringComparison.InvariantCulture:
364-
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None);
364+
return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, CompareOptions.None);
365365

366366
case StringComparison.InvariantCultureIgnoreCase:
367-
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
367+
return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
368368

369369
case StringComparison.Ordinal:
370-
return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.Ordinal);
370+
return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, ignoreCase: false);
371371

372372
case StringComparison.OrdinalIgnoreCase:
373-
return TextInfo.IndexOfStringOrdinalIgnoreCase(this, value, startIndex, count);
373+
return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, ignoreCase: true);
374374

375375
default:
376376
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
@@ -589,16 +589,16 @@ public int LastIndexOf(String value, int startIndex, int count, StringComparison
589589
return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
590590

591591
case StringComparison.InvariantCulture:
592-
return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.None);
592+
return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, CompareOptions.None);
593593

594594
case StringComparison.InvariantCultureIgnoreCase:
595-
return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
595+
return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
596596

597597
case StringComparison.Ordinal:
598-
return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.Ordinal);
598+
return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, ignoreCase: false);
599599

600600
case StringComparison.OrdinalIgnoreCase:
601-
return TextInfo.LastIndexOfStringOrdinalIgnoreCase(this, value, startIndex, count);
601+
return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, ignoreCase: true);
602602

603603
default:
604604
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));

src/mscorlib/src/System/Globalization/CultureInfo.cs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public partial class CultureInfo : IFormatProvider, ICloneable
113113
// Get in touch with the diagnostics team if you have questions.
114114

115115
//The Invariant culture;
116-
private static volatile CultureInfo s_InvariantCultureInfo;
116+
private static readonly CultureInfo s_InvariantCultureInfo = new CultureInfo(CultureData.Invariant, isReadOnly: true);
117117

118118
//These are defaults that we use if a thread has not opted into having an explicit culture
119119
private static volatile CultureInfo s_DefaultThreadCurrentUICulture;
@@ -156,13 +156,6 @@ internal static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs<Cu
156156
private static readonly bool init = Init();
157157
private static bool Init()
158158
{
159-
if (s_InvariantCultureInfo == null)
160-
{
161-
CultureInfo temp = new CultureInfo("", false);
162-
temp._isReadOnly = true;
163-
s_InvariantCultureInfo = temp;
164-
}
165-
166159
s_userDefaultCulture = GetUserDefaultCulture();
167160
s_userDefaultUICulture = GetUserDefaultUILanguage();
168161
return true;
@@ -192,12 +185,13 @@ public CultureInfo(String name, bool useUserOverride)
192185
InitializeFromName(name, useUserOverride);
193186
}
194187

195-
private CultureInfo(CultureData cultureData)
188+
private CultureInfo(CultureData cultureData, bool isReadOnly = false)
196189
{
197190
Debug.Assert(cultureData != null);
198191
_cultureData = cultureData;
199192
_name = cultureData.CultureName;
200193
_isInherited = false;
194+
_isReadOnly = isReadOnly;
201195
}
202196

203197
private static CultureInfo CreateCultureInfoNoThrow(string name, bool useUserOverride)
@@ -508,6 +502,7 @@ public static CultureInfo InvariantCulture
508502
{
509503
get
510504
{
505+
Debug.Assert(s_InvariantCultureInfo != null);
511506
return (s_InvariantCultureInfo);
512507
}
513508
}
@@ -1055,7 +1050,7 @@ public CultureInfo GetConsoleFallbackUICulture()
10551050
if (temp == null)
10561051
{
10571052
temp = CreateSpecificCulture(_cultureData.SCONSOLEFALLBACKNAME);
1058-
_isReadOnly = true;
1053+
temp._isReadOnly = true;
10591054
_consoleFallbackCulture = temp;
10601055
}
10611056
return (temp);

src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,10 @@ private Stream CaseInsensitiveManifestResourceStreamLookup(RuntimeAssembly satel
357357
sb.Append(name);
358358

359359
String givenName = sb.ToString();
360-
CompareInfo comparer = CultureInfo.InvariantCulture.CompareInfo;
361360
String canonicalName = null;
362361
foreach (String existingName in satellite.GetManifestResourceNames())
363362
{
364-
if (comparer.Compare(existingName, givenName, CompareOptions.IgnoreCase) == 0)
363+
if (String.Equals(existingName, givenName, StringComparison.InvariantCultureIgnoreCase))
365364
{
366365
if (canonicalName == null)
367366
{

src/mscorlib/src/System/String.Comparison.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,10 @@ public static int Compare(String strA, String strB, StringComparison comparisonT
395395
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);
396396

397397
case StringComparison.InvariantCulture:
398-
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);
398+
return CompareInfo.Invariant.Compare(strA, strB, CompareOptions.None);
399399

400400
case StringComparison.InvariantCultureIgnoreCase:
401-
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);
401+
return CompareInfo.Invariant.Compare(strA, strB, CompareOptions.IgnoreCase);
402402

403403
case StringComparison.Ordinal:
404404
// Most common case: first character is different.
@@ -592,10 +592,10 @@ public static int Compare(String strA, int indexA, String strB, int indexB, int
592592
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
593593

594594
case StringComparison.InvariantCulture:
595-
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
595+
return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
596596

597597
case StringComparison.InvariantCultureIgnoreCase:
598-
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
598+
return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
599599

600600
case StringComparison.Ordinal:
601601
return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB);
@@ -771,10 +771,10 @@ public Boolean EndsWith(String value, StringComparison comparisonType)
771771
return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, CompareOptions.IgnoreCase);
772772

773773
case StringComparison.InvariantCulture:
774-
return CultureInfo.InvariantCulture.CompareInfo.IsSuffix(this, value, CompareOptions.None);
774+
return CompareInfo.Invariant.IsSuffix(this, value, CompareOptions.None);
775775

776776
case StringComparison.InvariantCultureIgnoreCase:
777-
return CultureInfo.InvariantCulture.CompareInfo.IsSuffix(this, value, CompareOptions.IgnoreCase);
777+
return CompareInfo.Invariant.IsSuffix(this, value, CompareOptions.IgnoreCase);
778778

779779
case StringComparison.Ordinal:
780780
return this.Length < value.Length ? false : (CompareOrdinalHelper(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
@@ -867,10 +867,10 @@ public bool Equals(String value, StringComparison comparisonType)
867867
return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, CompareOptions.IgnoreCase) == 0);
868868

869869
case StringComparison.InvariantCulture:
870-
return (CultureInfo.InvariantCulture.CompareInfo.Compare(this, value, CompareOptions.None) == 0);
870+
return (CompareInfo.Invariant.Compare(this, value, CompareOptions.None) == 0);
871871

872872
case StringComparison.InvariantCultureIgnoreCase:
873-
return (CultureInfo.InvariantCulture.CompareInfo.Compare(this, value, CompareOptions.IgnoreCase) == 0);
873+
return (CompareInfo.Invariant.Compare(this, value, CompareOptions.IgnoreCase) == 0);
874874

875875
case StringComparison.Ordinal:
876876
if (this.Length != value.Length)
@@ -935,10 +935,10 @@ public static bool Equals(String a, String b, StringComparison comparisonType)
935935
return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0);
936936

937937
case StringComparison.InvariantCulture:
938-
return (CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0);
938+
return (CompareInfo.Invariant.Compare(a, b, CompareOptions.None) == 0);
939939

940940
case StringComparison.InvariantCultureIgnoreCase:
941-
return (CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0);
941+
return (CompareInfo.Invariant.Compare(a, b, CompareOptions.IgnoreCase) == 0);
942942

943943
case StringComparison.Ordinal:
944944
if (a.Length != b.Length)
@@ -1090,10 +1090,10 @@ public Boolean StartsWith(String value, StringComparison comparisonType)
10901090
return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase);
10911091

10921092
case StringComparison.InvariantCulture:
1093-
return CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this, value, CompareOptions.None);
1093+
return CompareInfo.Invariant.IsPrefix(this, value, CompareOptions.None);
10941094

10951095
case StringComparison.InvariantCultureIgnoreCase:
1096-
return CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase);
1096+
return CompareInfo.Invariant.IsPrefix(this, value, CompareOptions.IgnoreCase);
10971097

10981098
case StringComparison.Ordinal:
10991099
if (this.Length < value.Length || _firstChar != value._firstChar)

0 commit comments

Comments
 (0)