Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce allocations in CSharpSyntaxFacts.AppendMembers (again) #74790

Merged
merged 6 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -745,9 +745,11 @@ private async Task<bool> ProcessSuppressMessageAttributesAsync(
return false;
}

using var _1 = ArrayBuilder<SyntaxNode>.GetInstance(out var declarationNodes);
using var pooledDeclarationNodes = SharedPools.Default<List<SyntaxNode>>().GetPooledObject();
var declarationNodes = pooledDeclarationNodes.Object;

SyntaxFacts.AddTopLevelAndMethodLevelMembers(root, declarationNodes);
using var _2 = PooledHashSet<ISymbol>.GetInstance(out var processedPartialSymbols);
using var _ = PooledHashSet<ISymbol>.GetInstance(out var processedPartialSymbols);
if (declarationNodes.Count > 0)
{
foreach (var node in declarationNodes)
Expand Down
167 changes: 126 additions & 41 deletions src/Compilers/Core/Portable/Collections/ImmutableArrayExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -352,14 +352,14 @@ public static async ValueTask<ImmutableArray<TResult>> SelectAsArrayAsync<TItem,
if (array.IsEmpty)
return ImmutableArray<TResult>.Empty;

var builder = ArrayBuilder<TResult>.GetInstance(array.Length);
var builder = new TResult[array.Length];

foreach (var item in array)
for (var i = 0; i < array.Length; i++)
{
builder.Add(await selector(item, cancellationToken).ConfigureAwait(false));
builder[i] = await selector(array[i], cancellationToken).ConfigureAwait(false);
}

return builder.ToImmutableAndFree();
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}

/// <summary>
Expand All @@ -370,14 +370,14 @@ public static async ValueTask<ImmutableArray<TResult>> SelectAsArrayAsync<TItem,
if (array.IsEmpty)
return ImmutableArray<TResult>.Empty;

var builder = ArrayBuilder<TResult>.GetInstance(array.Length);
var builder = new TResult[array.Length];

foreach (var item in array)
for (var i = 0; i < array.Length; i++)
{
builder.Add(await selector(item, arg, cancellationToken).ConfigureAwait(false));
builder[i] = await selector(array[i], arg, cancellationToken).ConfigureAwait(false);
}

return builder.ToImmutableAndFree();
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}

public static ValueTask<ImmutableArray<TResult>> SelectManyAsArrayAsync<TItem, TArg, TResult>(this ImmutableArray<TItem> source, Func<TItem, TArg, CancellationToken, ValueTask<ImmutableArray<TResult>>> selector, TArg arg, CancellationToken cancellationToken)
Expand Down Expand Up @@ -432,13 +432,13 @@ public static ImmutableArray<TResult> ZipAsArray<T1, T2, TResult>(this Immutable
return ImmutableArray.Create(map(self[0], other[0]), map(self[1], other[1]), map(self[2], other[2]), map(self[3], other[3]));

default:
var builder = ArrayBuilder<TResult>.GetInstance(self.Length);
var builder = new TResult[self.Length];
for (int i = 0; i < self.Length; i++)
{
builder.Add(map(self[i], other[i]));
builder[i] = map(self[i], other[i]);
}

return builder.ToImmutableAndFree();
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}
}

Expand Down Expand Up @@ -815,44 +815,124 @@ internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, Immuta

internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, ImmutableArray<T> second, ImmutableArray<T> third)
{
var builder = ArrayBuilder<T>.GetInstance(first.Length + second.Length + third.Length);
builder.AddRange(first);
builder.AddRange(second);
builder.AddRange(third);
return builder.ToImmutableAndFree();
var builder = new T[first.Length + second.Length + third.Length];
var index = 0;

foreach (var item in first)
{
builder[index++] = item;
}

foreach (var item in second)
{
builder[index++] = item;
}

foreach (var item in third)
{
builder[index++] = item;
}

return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}

internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, ImmutableArray<T> second, ImmutableArray<T> third, ImmutableArray<T> fourth)
{
var builder = ArrayBuilder<T>.GetInstance(first.Length + second.Length + third.Length + fourth.Length);
builder.AddRange(first);
builder.AddRange(second);
builder.AddRange(third);
builder.AddRange(fourth);
return builder.ToImmutableAndFree();
var builder = new T[first.Length + second.Length + third.Length + fourth.Length];
var index = 0;

foreach (var item in first)
{
builder[index++] = item;
}

foreach (var item in second)
{
builder[index++] = item;
}

foreach (var item in third)
{
builder[index++] = item;
}

foreach (var item in fourth)
{
builder[index++] = item;
}

return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}

internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, ImmutableArray<T> second, ImmutableArray<T> third, ImmutableArray<T> fourth, ImmutableArray<T> fifth)
{
var builder = ArrayBuilder<T>.GetInstance(first.Length + second.Length + third.Length + fourth.Length + fifth.Length);
builder.AddRange(first);
builder.AddRange(second);
builder.AddRange(third);
builder.AddRange(fourth);
builder.AddRange(fifth);
return builder.ToImmutableAndFree();
var builder = new T[first.Length + second.Length + third.Length + fourth.Length + fifth.Length];
var index = 0;

foreach (var item in first)
{
builder[index++] = item;
}

foreach (var item in second)
{
builder[index++] = item;
}

foreach (var item in third)
{
builder[index++] = item;
}

foreach (var item in fourth)
{
builder[index++] = item;
}

foreach (var item in fifth)
{
builder[index++] = item;
}

return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}

internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, ImmutableArray<T> second, ImmutableArray<T> third, ImmutableArray<T> fourth, ImmutableArray<T> fifth, ImmutableArray<T> sixth)
{
var builder = ArrayBuilder<T>.GetInstance(first.Length + second.Length + third.Length + fourth.Length + fifth.Length + sixth.Length);
builder.AddRange(first);
builder.AddRange(second);
builder.AddRange(third);
builder.AddRange(fourth);
builder.AddRange(fifth);
builder.AddRange(sixth);
return builder.ToImmutableAndFree();
var builder = new T[first.Length + second.Length + third.Length + fourth.Length + fifth.Length + sixth.Length];
var index = 0;

foreach (var item in first)
{
builder[index++] = item;
}

foreach (var item in second)
{
builder[index++] = item;
}

foreach (var item in third)
{
builder[index++] = item;
}

foreach (var item in fourth)
{
builder[index++] = item;
}

foreach (var item in fifth)
{
builder[index++] = item;
}

foreach (var item in sixth)
{
builder[index++] = item;
}

return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}

internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, T second)
Expand All @@ -872,15 +952,20 @@ internal static ImmutableArray<T> AddRange<T>(this ImmutableArray<T> self, in Te
return self.Add(items[0]);
}

var builder = ArrayBuilder<T>.GetInstance(self.Length + items.Count);
builder.AddRange(self);
var builder = new T[self.Length + items.Count];
var index = 0;

foreach (var item in self)
{
builder[index++] = item;
}

foreach (var item in items)
{
builder.Add(item);
builder[index++] = item;
}

return builder.ToImmutableAndFree();
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
Expand Down Expand Up @@ -385,11 +386,15 @@ public static ImmutableArray<TResult> SelectAsArray<TSource, TResult>(this IRead
if (source == null)
return ImmutableArray<TResult>.Empty;

var builder = ArrayBuilder<TResult>.GetInstance(source.Count);
var builder = new TResult[source.Count];
333fred marked this conversation as resolved.
Show resolved Hide resolved
var index = 0;
foreach (var item in source)
builder.Add(selector(item));
{
builder[index] = selector(item);
index++;
}

return builder.ToImmutableAndFree();
return ImmutableCollectionsMarshal.AsImmutableArray(builder);
}

public static ImmutableArray<TResult> SelectManyAsArray<TSource, TResult>(this IEnumerable<TSource>? source, Func<TSource, IEnumerable<TResult>> selector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
#nullable disable

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Commanding;
Expand Down Expand Up @@ -103,7 +103,8 @@ private bool ExecuteCommandImpl(EditorCommandArgs args, bool gotoNextMember, Com
/// </summary>
internal static int? GetTargetPosition(ISyntaxFactsService service, SyntaxNode root, int caretPosition, bool next)
{
using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var members);
using var pooledMembers = SharedPools.Default<List<SyntaxNode>>().GetPooledObject();
var members = pooledMembers.Object;

service.AddMethodLevelMembers(root, members);
if (members.Count == 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
Expand Down Expand Up @@ -215,7 +216,8 @@ async Task ExecuteAnalyzersAsync(
return null;
}

using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var members);
using var pooledMembers = SharedPools.Default<List<SyntaxNode>>().GetPooledObject();
var members = pooledMembers.Object;

var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>();
syntaxFacts.AddMethodLevelMembers(root, members);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
Expand Down Expand Up @@ -47,7 +47,9 @@ static async Task<ImmutableArray<TextSpan>> CreateMemberSpansAsync(Document docu
var service = document.GetRequiredLanguageService<ISyntaxFactsService>();
var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var members);
using var pooledMembers = SharedPools.Default<List<SyntaxNode>>().GetPooledObject();
var members = pooledMembers.Object;

service.AddMethodLevelMembers(root, members);
return members.SelectAsArray(m => m.FullSpan);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.PooledObjects;

namespace Microsoft.CodeAnalysis.SemanticModelReuse;

Expand Down Expand Up @@ -106,7 +106,9 @@ protected SyntaxNode GetPreviousBodyNode(SyntaxNode previousRoot, SyntaxNode cur
}
else
{
using var _1 = ArrayBuilder<SyntaxNode>.GetInstance(out var currentMembers);
using var pooledCurrentMembers = SharedPools.Default<List<SyntaxNode>>().GetPooledObject();
var currentMembers = pooledCurrentMembers.Object;

this.SyntaxFacts.AddMethodLevelMembers(currentRoot, currentMembers);
var index = currentMembers.IndexOf(currentBodyNode);
if (index < 0)
Expand All @@ -115,7 +117,9 @@ protected SyntaxNode GetPreviousBodyNode(SyntaxNode previousRoot, SyntaxNode cur
return null;
}

using var _2 = ArrayBuilder<SyntaxNode>.GetInstance(out var previousMembers);
using var pooledPreviousMembers = SharedPools.Default<List<SyntaxNode>>().GetPooledObject();
var previousMembers = pooledPreviousMembers.Object;

this.SyntaxFacts.AddMethodLevelMembers(previousRoot, previousMembers);
if (currentMembers.Count != previousMembers.Count)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -896,20 +896,20 @@ private static void AppendTypeParameterList(StringBuilder builder, TypeParameter
}
}

public void AddTopLevelAndMethodLevelMembers(SyntaxNode? root, ArrayBuilder<SyntaxNode> list)
public void AddTopLevelAndMethodLevelMembers(SyntaxNode? root, List<SyntaxNode> list)
{
AppendMembers(root, list, topLevel: true, methodLevel: true);
}

public void AddMethodLevelMembers(SyntaxNode? root, ArrayBuilder<SyntaxNode> list)
public void AddMethodLevelMembers(SyntaxNode? root, List<SyntaxNode> list)
{
AppendMembers(root, list, topLevel: false, methodLevel: true);
}

public SyntaxList<SyntaxNode> GetMembersOfTypeDeclaration(SyntaxNode typeDeclaration)
=> ((TypeDeclarationSyntax)typeDeclaration).Members;

private void AppendMembers(SyntaxNode? node, ArrayBuilder<SyntaxNode> list, bool topLevel, bool methodLevel)
private void AppendMembers(SyntaxNode? node, List<SyntaxNode> list, bool topLevel, bool methodLevel)
{
Debug.Assert(topLevel || methodLevel);

Expand Down
Loading
Loading