Skip to content

Commit 2d01ce7

Browse files
authored
Reduce allocations during CommonCompletionItem.Create (#79591)
I noticed this when looking at a ManagedLangsVS64.Typing test profile. CommonCompletionItem.Create accounts for about 1.4% of allocations in the test, about 1/3 of which is due to some linq usage. This change just expands that linq out and reduces the amount of data the method needs generated for it.
1 parent 6962adc commit 2d01ce7

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

src/Features/Core/Portable/Common/TaggedText.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ public static ImmutableArray<TaggedText> ToTaggedText(
103103
includeNavigationHints && d.Kind != SymbolDisplayPartKind.NamespaceName ? getNavigationHint(d.Symbol) : null));
104104
}
105105

106+
public static ImmutableArray<(string tag, string text)> ToTagsAndText(this ImmutableArray<SymbolDisplayPart> displayParts)
107+
=> displayParts.SelectAsArray(static d => (GetTag(d), d.ToString()));
108+
106109
private static string GetTag(SymbolDisplayPart part)
107110
{
108111
// We don't actually have any specific classifications for aliases. So if the compiler passed us that kind,

src/Features/Core/Portable/Completion/CommonCompletionItem.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Collections.Immutable;
77
using System.Linq;
8+
using Microsoft.CodeAnalysis.PooledObjects;
89
using Microsoft.CodeAnalysis.Tags;
910
using Roslyn.Utilities;
1011

@@ -44,7 +45,7 @@ public static CompletionItem Create(
4445

4546
if (!description.IsDefault && description.Length > 0)
4647
{
47-
properties = properties.NullToEmpty().Add(KeyValuePair.Create(DescriptionProperty, EncodeDescription(description.ToTaggedText())));
48+
properties = properties.NullToEmpty().Add(KeyValuePair.Create(DescriptionProperty, EncodeDescription(description.ToTagsAndText())));
4849
}
4950

5051
return CompletionItem.CreateInternal(
@@ -77,8 +78,25 @@ public static CompletionDescription GetDescription(CompletionItem item)
7778

7879
private static readonly char[] s_descriptionSeparators = ['|'];
7980

80-
private static string EncodeDescription(ImmutableArray<TaggedText> description)
81-
=> string.Join("|", description.SelectMany(d => new[] { d.Tag, d.Text }).Select(t => t.Escape('\\', s_descriptionSeparators)));
81+
private static string EncodeDescription(ImmutableArray<(string tag, string text)> description)
82+
{
83+
using var _ = PooledStringBuilder.GetInstance(out var builder);
84+
85+
foreach (var (tag, text) in description)
86+
{
87+
var escapedTag = tag.Escape('\\', s_descriptionSeparators);
88+
var escapedText = text.Escape('\\', s_descriptionSeparators);
89+
90+
if (builder.Length > 0)
91+
builder.Append('|');
92+
93+
builder.Append(escapedTag);
94+
builder.Append('|');
95+
builder.Append(escapedText);
96+
}
97+
98+
return builder.ToString();
99+
}
82100

83101
private static CompletionDescription DecodeDescription(string encoded)
84102
{

0 commit comments

Comments
 (0)