Skip to content

Commit e1aeac8

Browse files
authored
Remove some low hanging allocations (#35397)
* [x] In the ordinary case, diagnostics aren't produced by builders. The current pattern results in allocating a HashSet and an empty array for this case. Removing some of these allocations * [x] ViewComponentTagHelperPass does not need to operate on .razor files, but does some unnecessary work. We can avoid it
1 parent a0193e2 commit e1aeac8

10 files changed

+132
-63
lines changed

src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/CreateNewOnMetadataUpdateAttributePass.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ internal sealed class CreateNewOnMetadataUpdateAttributePass : IntermediateNodeP
1616
{
1717
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
1818
{
19-
if (FileKinds.IsComponent(codeDocument.GetFileKind()))
19+
if (documentNode.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
20+
documentNode.DocumentKind != MvcViewDocumentClassifierPass.MvcViewDocumentKind)
2021
{
21-
// Hot reload does not apply to components.
22+
// Not a MVC file. Skip.
2223
return;
2324
}
2425

src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/ModelExpressionPass.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
@@ -15,6 +15,13 @@ public class ModelExpressionPass : IntermediateNodePassBase, IRazorOptimizationP
1515

1616
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
1717
{
18+
if (documentNode.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
19+
documentNode.DocumentKind != MvcViewDocumentClassifierPass.MvcViewDocumentKind)
20+
{
21+
// Not a MVC file. Skip.
22+
return;
23+
}
24+
1825
var visitor = new Visitor();
1926
visitor.Visit(documentNode);
2027
}

src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/src/ViewComponentTagHelperPass.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Generic;
@@ -15,6 +15,13 @@ public class ViewComponentTagHelperPass : IntermediateNodePassBase, IRazorOptimi
1515

1616
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
1717
{
18+
if (documentNode.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
19+
documentNode.DocumentKind != MvcViewDocumentClassifierPass.MvcViewDocumentKind)
20+
{
21+
// Not a MVC file. Skip.
22+
return;
23+
}
24+
1825
var @namespace = documentNode.FindPrimaryNamespace();
1926
var @class = documentNode.FindPrimaryClass();
2027
if (@namespace == null || @class == null)

src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ModelExpressionPassTest.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ private DocumentIntermediateNode CreateIRDocument(RazorEngine engine, RazorCodeD
170170
}
171171
}
172172

173-
return codeDocument.GetDocumentIntermediateNode();
173+
var irNode = codeDocument.GetDocumentIntermediateNode();
174+
irNode.DocumentKind = MvcViewDocumentClassifierPass.MvcViewDocumentKind;
175+
176+
return irNode;
174177
}
175178

176179
private TagHelperIntermediateNode FindTagHelperNode(IntermediateNode node)
@@ -205,4 +208,4 @@ public override void VisitTagHelper(TagHelperIntermediateNode node)
205208
}
206209
}
207210
}
208-
}
211+
}

src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultAllowedChildTagDescriptorBuilder.cs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
@@ -36,42 +36,46 @@ public override RazorDiagnosticCollection Diagnostics
3636

3737
public AllowedChildTagDescriptor Build()
3838
{
39-
var validationDiagnostics = Validate();
40-
var diagnostics = new HashSet<RazorDiagnostic>(validationDiagnostics);
39+
var diagnostics = Validate();
4140
if (_diagnostics != null)
4241
{
42+
diagnostics ??= new();
4343
diagnostics.UnionWith(_diagnostics);
4444
}
4545

4646
var displayName = DisplayName ?? Name;
4747
var descriptor = new DefaultAllowedChildTagDescriptor(
4848
Name,
4949
displayName,
50-
diagnostics.ToArray());
50+
diagnostics?.ToArray() ?? Array.Empty<RazorDiagnostic>());
5151

5252
return descriptor;
5353
}
5454

55-
private IEnumerable<RazorDiagnostic> Validate()
55+
private HashSet<RazorDiagnostic> Validate()
5656
{
57+
HashSet<RazorDiagnostic> diagnostics = null;
5758
if (string.IsNullOrWhiteSpace(Name))
5859
{
5960
var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidRestrictedChildNullOrWhitespace(_parent.GetDisplayName());
6061

61-
yield return diagnostic;
62+
diagnostics ??= new();
63+
diagnostics.Add(diagnostic);
6264
}
6365
else if (Name != TagHelperMatchingConventions.ElementCatchAllName)
6466
{
6567
foreach (var character in Name)
6668
{
67-
if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character))
69+
if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character))
6870
{
6971
var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidRestrictedChild(_parent.GetDisplayName(), Name, character);
70-
71-
yield return diagnostic;
72+
diagnostics ??= new();
73+
diagnostics.Add(diagnostic);
7274
}
7375
}
7476
}
77+
78+
return diagnostics;
7579
}
7680
}
7781
}

src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultBoundAttributeDescriptorBuilder.cs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,10 @@ public override void BindAttributeParameter(Action<BoundAttributeParameterDescri
9292

9393
public BoundAttributeDescriptor Build()
9494
{
95-
var validationDiagnostics = Validate();
96-
var diagnostics = new HashSet<RazorDiagnostic>(validationDiagnostics);
95+
var diagnostics = Validate();
9796
if (_diagnostics != null)
9897
{
98+
diagnostics ??= new();
9999
diagnostics.UnionWith(_diagnostics);
100100
}
101101

@@ -125,7 +125,7 @@ public BoundAttributeDescriptor Build()
125125
CaseSensitive,
126126
parameters,
127127
new Dictionary<string, string>(Metadata),
128-
diagnostics.ToArray())
128+
diagnostics?.ToArray() ?? Array.Empty<RazorDiagnostic>())
129129
{
130130
IsEditorRequired = IsEditorRequired,
131131
};
@@ -159,13 +159,15 @@ private string GetDisplayName()
159159
return Name;
160160
}
161161

162-
private IEnumerable<RazorDiagnostic> Validate()
162+
private HashSet<RazorDiagnostic> Validate()
163163
{
164164
// data-* attributes are explicitly not implemented by user agents and are not intended for use on
165165
// the server; therefore it's invalid for TagHelpers to bind to them.
166166
const string DataDashPrefix = "data-";
167167
var isDirectiveAttribute = this.IsDirectiveAttribute();
168168

169+
HashSet<RazorDiagnostic> diagnostics = null;
170+
169171
if (string.IsNullOrWhiteSpace(Name))
170172
{
171173
if (IndexerAttributeNamePrefix == null)
@@ -174,7 +176,8 @@ private IEnumerable<RazorDiagnostic> Validate()
174176
_parent.GetDisplayName(),
175177
GetDisplayName());
176178

177-
yield return diagnostic;
179+
diagnostics ??= new();
180+
diagnostics.Add(diagnostic);
178181
}
179182
}
180183
else
@@ -186,7 +189,8 @@ private IEnumerable<RazorDiagnostic> Validate()
186189
GetDisplayName(),
187190
Name);
188191

189-
yield return diagnostic;
192+
diagnostics ??= new();
193+
diagnostics.Add(diagnostic);
190194
}
191195

192196
StringSegment name = Name;
@@ -201,21 +205,23 @@ private IEnumerable<RazorDiagnostic> Validate()
201205
GetDisplayName(),
202206
Name);
203207

204-
yield return diagnostic;
208+
diagnostics ??= new();
209+
diagnostics.Add(diagnostic);
205210
}
206211

207212
for (var i = 0; i < name.Length; i++)
208213
{
209214
var character = name[i];
210-
if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character))
215+
if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character))
211216
{
212217
var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeName(
213218
_parent.GetDisplayName(),
214219
GetDisplayName(),
215220
name.Value,
216221
character);
217222

218-
yield return diagnostic;
223+
diagnostics ??= new();
224+
diagnostics.Add(diagnostic);
219225
}
220226
}
221227
}
@@ -229,15 +235,17 @@ private IEnumerable<RazorDiagnostic> Validate()
229235
GetDisplayName(),
230236
IndexerAttributeNamePrefix);
231237

232-
yield return diagnostic;
238+
diagnostics ??= new();
239+
diagnostics.Add(diagnostic);
233240
}
234241
else if (IndexerAttributeNamePrefix.Length > 0 && string.IsNullOrWhiteSpace(IndexerAttributeNamePrefix))
235242
{
236243
var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeNullOrWhitespace(
237244
_parent.GetDisplayName(),
238245
GetDisplayName());
239246

240-
yield return diagnostic;
247+
diagnostics ??= new();
248+
diagnostics.Add(diagnostic);
241249
}
242250
else
243251
{
@@ -253,25 +261,29 @@ private IEnumerable<RazorDiagnostic> Validate()
253261
GetDisplayName(),
254262
indexerPrefix.Value);
255263

256-
yield return diagnostic;
264+
diagnostics ??= new();
265+
diagnostics.Add(diagnostic);
257266
}
258267

259268
for (var i = 0; i < indexerPrefix.Length; i++)
260269
{
261270
var character = indexerPrefix[i];
262-
if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character))
271+
if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character))
263272
{
264273
var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributePrefix(
265274
_parent.GetDisplayName(),
266275
GetDisplayName(),
267276
indexerPrefix.Value,
268277
character);
269278

270-
yield return diagnostic;
279+
diagnostics ??= new();
280+
diagnostics.Add(diagnostic);
271281
}
272282
}
273283
}
274284
}
285+
286+
return diagnostics;
275287
}
276288

277289
private void EnsureAttributeParameterBuilders()

src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultBoundAttributeParameterDescriptorBuilder.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.Linq;
67

@@ -51,10 +52,10 @@ public override RazorDiagnosticCollection Diagnostics
5152

5253
public BoundAttributeParameterDescriptor Build()
5354
{
54-
var validationDiagnostics = Validate();
55-
var diagnostics = new HashSet<RazorDiagnostic>(validationDiagnostics);
55+
var diagnostics = Validate();
5656
if (_diagnostics != null)
5757
{
58+
diagnostics ??= new();
5859
diagnostics.UnionWith(_diagnostics);
5960
}
6061
var descriptor = new DefaultBoundAttributeParameterDescriptor(
@@ -66,7 +67,7 @@ public BoundAttributeParameterDescriptor Build()
6667
GetDisplayName(),
6768
CaseSensitive,
6869
new Dictionary<string, string>(Metadata),
69-
diagnostics.ToArray());
70+
diagnostics?.ToArray() ?? Array.Empty<RazorDiagnostic>());
7071

7172
return descriptor;
7273
}
@@ -81,28 +82,34 @@ private string GetDisplayName()
8182
return $":{Name}";
8283
}
8384

84-
private IEnumerable<RazorDiagnostic> Validate()
85+
private HashSet<RazorDiagnostic> Validate()
8586
{
87+
HashSet<RazorDiagnostic> diagnostics = null;
8688
if (string.IsNullOrWhiteSpace(Name))
8789
{
90+
8891
var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeParameterNullOrWhitespace(_parent.Name);
89-
yield return diagnostic;
92+
diagnostics ??= new();
93+
diagnostics.Add(diagnostic);
9094
}
9195
else
9296
{
9397
foreach (var character in Name)
9498
{
95-
if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character))
99+
if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character))
96100
{
97101
var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeParameterName(
98102
_parent.Name,
99103
Name,
100104
character);
101105

102-
yield return diagnostic;
106+
diagnostics ??= new();
107+
diagnostics.Add(diagnostic);
103108
}
104109
}
105110
}
111+
112+
return diagnostics;
106113
}
107114
}
108115
}

0 commit comments

Comments
 (0)