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 Razor's DirectiveVisitor #10537

Merged
merged 2 commits into from
Jun 27, 2024
Merged
Changes from all 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 @@ -53,22 +53,25 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument)
visitor = new TagHelperDirectiveVisitor(descriptors, matches);
}

if (codeDocument.GetImportSyntaxTrees() is { IsDefault: false } imports)
using (visitor)
{
foreach (var import in imports)
if (codeDocument.GetImportSyntaxTrees() is { IsDefault: false } imports)
{
visitor.Visit(import);
foreach (var import in imports)
{
visitor.Visit(import);
}
}
}

visitor.Visit(syntaxTree);
visitor.Visit(syntaxTree);

// This will always be null for a component document.
var tagHelperPrefix = visitor.TagHelperPrefix;
// This will always be null for a component document.
var tagHelperPrefix = visitor.TagHelperPrefix;

var context = TagHelperDocumentContext.Create(tagHelperPrefix, matches.ToImmutableArray());
codeDocument.SetTagHelperContext(context);
codeDocument.SetPreTagHelperSyntaxTree(syntaxTree);
var context = TagHelperDocumentContext.Create(tagHelperPrefix, matches.ToImmutableArray());
codeDocument.SetTagHelperContext(context);
codeDocument.SetPreTagHelperSyntaxTree(syntaxTree);
}
}

private static bool MatchesDirective(TagHelperDescriptor descriptor, string typePattern, string assemblyName)
Expand Down Expand Up @@ -106,25 +109,27 @@ private static ReadOnlySpan<char> RemoveGlobalPrefix(in ReadOnlySpan<char> span)
return span;
}

internal abstract class DirectiveVisitor(HashSet<TagHelperDescriptor> matches) : SyntaxWalker
internal abstract class DirectiveVisitor(HashSet<TagHelperDescriptor> matches) : SyntaxWalker, IDisposable
{
protected readonly HashSet<TagHelperDescriptor> Matches = matches;

public abstract string TagHelperPrefix { get; }

public abstract void Visit(RazorSyntaxTree tree);

public abstract void Dispose();
}

internal sealed class TagHelperDirectiveVisitor : DirectiveVisitor
{
private readonly List<TagHelperDescriptor> _tagHelpers;
private List<TagHelperDescriptor> _tagHelpers;
private string _tagHelperPrefix;

public TagHelperDirectiveVisitor(IReadOnlyList<TagHelperDescriptor> tagHelpers, HashSet<TagHelperDescriptor> matches)
: base(matches)
{
// We don't want to consider components in a view document.
_tagHelpers = new();
_tagHelpers = ListPool<TagHelperDescriptor>.Default.Get();

for (var i = 0; i < tagHelpers.Count; i++)
{
Expand Down Expand Up @@ -229,11 +234,20 @@ private static bool AssemblyContainsTagHelpers(string assemblyName, List<TagHelp

return false;
}

public override void Dispose()
{
if (_tagHelpers != null)
{
ListPool<TagHelperDescriptor>.Default.Return(_tagHelpers);
_tagHelpers = null;
}
}
}

internal sealed class ComponentDirectiveVisitor : DirectiveVisitor
{
private readonly ImmutableArray<TagHelperDescriptor> _notFullyQualifiedComponents;
private List<TagHelperDescriptor> _notFullyQualifiedComponents;
private readonly string _filePath;
private RazorSourceDocument _source;

Expand All @@ -242,7 +256,7 @@ public ComponentDirectiveVisitor(string filePath, IReadOnlyList<TagHelperDescrip
{
_filePath = filePath;

using var builder = new PooledArrayBuilder<TagHelperDescriptor>(capacity: tagHelpers.Count);
_notFullyQualifiedComponents = ListPool<TagHelperDescriptor>.Default.Get();

for (var i = 0; i < tagHelpers.Count; i++)
{
Expand All @@ -260,7 +274,7 @@ public ComponentDirectiveVisitor(string filePath, IReadOnlyList<TagHelperDescrip
continue;
}

builder.Add(tagHelper);
_notFullyQualifiedComponents.Add(tagHelper);

if (currentNamespace is null)
{
Expand All @@ -282,8 +296,6 @@ public ComponentDirectiveVisitor(string filePath, IReadOnlyList<TagHelperDescrip
Matches.Add(tagHelper);
}
}

_notFullyQualifiedComponents = builder.DrainToImmutable();
}

// There is no support for tag helper prefix in component documents.
Expand Down Expand Up @@ -427,5 +439,14 @@ internal static bool IsTagHelperFromMangledClass(TagHelperDescriptor tagHelper)
{
return ComponentMetadata.IsMangledClass(tagHelper.GetTypeNameIdentifier());
}

public override void Dispose()
{
if (_notFullyQualifiedComponents != null)
{
ListPool<TagHelperDescriptor>.Default.Return(_notFullyQualifiedComponents);
_notFullyQualifiedComponents = null;
}
}
}
}
Loading