提交 1bba8770 编写于 作者: P Pharring

MetadataHelpers.SplitQualifiedName interllay uses string.Split. This results...

MetadataHelpers.SplitQualifiedName interllay uses string.Split. This results in an allocation. The allocation is immediately converted to an ImmutableArray.

This change replaces string.Split with a hand-rolled algorithm that tries to avoid allocations. First, zero or 1 length arrays avoid any intermediate allocations.
For larger results, the exact length is precomputed and we try to get an ArrayBuilder from the pool.
As a bonus, since "System" is such a frequent first string, we avoid a new substring allocation. (changeset 1213621)
上级 75120d43
......@@ -206,7 +206,7 @@ public override Symbol ContainingSymbol
if (namespaceName.Length > 0)
{
string[] namespaces = MetadataHelpers.SplitQualifiedName(namespaceName);
var namespaces = MetadataHelpers.SplitQualifiedName(namespaceName);
int i;
for (i = 0; i < namespaces.Length; i++)
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
......@@ -19,6 +20,7 @@ internal static class MetadataHelpers
public const string GenericTypeNameManglingString = "`";
public const int MaxStringLengthForParamSize = 22;
public const int MaxStringLengthForIntToStringConversion = 22;
public const string SystemString = "System";
internal struct AssemblyQualifiedTypeName
{
......@@ -486,12 +488,63 @@ internal static string UnmangleMetadataNameForArity(string emittedTypeName, int
return emittedTypeName;
}
internal static string[] SplitQualifiedName(
string pstrName)
/// <summary>
/// An ImmutableArray representing the single string "System"
/// </summary>
private static readonly ImmutableArray<string> SplitQualifiedNameSystem = ImmutableArray.Create(SystemString);
internal static ImmutableArray<string> SplitQualifiedName(
string name)
{
Debug.Assert(pstrName != null);
Debug.Assert(name != null);
return pstrName.Split(DotDelimiter);
if (name.Length == 0)
{
return ImmutableArray<string>.Empty;
}
// PERF: Avoid String.Split because of the allocations. Also, we can special-case
// for "System" if it is the first or only part.
int dots = 0;
foreach (char ch in name)
{
if (ch == DotDelimiter)
{
dots++;
}
}
if (dots == 0)
{
return name == SystemString ? SplitQualifiedNameSystem : ImmutableArray.Create(name);
}
var result = ArrayBuilder<string>.GetInstance(dots + 1);
int start = 0;
for (int i = 0; dots > 0; i++)
{
if (name[i] == DotDelimiter)
{
int len = i - start;
if (len == 6 && start == 0 && name.StartsWith(SystemString))
{
result.Add(SystemString);
}
else
{
result.Add(name.Substring(start, len));
}
dots--;
start = i + 1;
}
}
result.Add(name.Substring(start));
return result.ToImmutableAndFree();
}
internal static string SplitQualifiedName(
......@@ -508,7 +561,14 @@ internal static string UnmangleMetadataNameForArity(string emittedTypeName, int
return pstrName;
}
if (delimiter == 6 && pstrName.StartsWith(SystemString))
{
qualifier = SystemString;
}
else
{
qualifier = pstrName.Substring(0, delimiter);
}
return pstrName.Substring(delimiter + 1);
}
......
......@@ -273,16 +273,7 @@ public ImmutableArray<string> NamespaceSegments
{
if (namespaceSegments.IsDefault)
{
string nsName = NamespaceName;
if (nsName.Length == 0)
{
namespaceSegments = ImmutableArray<string>.Empty;
}
else
{
namespaceSegments = MetadataHelpers.SplitQualifiedName(nsName).AsImmutableOrNull();
}
namespaceSegments = MetadataHelpers.SplitQualifiedName(NamespaceName);
}
return namespaceSegments;
......
......@@ -129,7 +129,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim container As NamespaceSymbol = m_ContainingModule.GlobalNamespace
If m_NamespaceName.Length > 0 Then
Dim namespaces() As String = MetadataHelpers.SplitQualifiedName(m_NamespaceName)
Dim namespaces = MetadataHelpers.SplitQualifiedName(m_NamespaceName)
Dim i As Integer
For i = 0 To namespaces.Length - 1 Step 1
......
......@@ -324,7 +324,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return ImmutableArray(Of String).Empty
End If
Return MetadataHelpers.SplitQualifiedName(_rootNamespace).AsImmutableOrNull()
Return MetadataHelpers.SplitQualifiedName(_rootNamespace)
End Function
''' <summary>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册