Move IsSpacingToken perf optimizations down to base class (#22555)
This gives the HtmlMarkupParser the same non-allocating behavior for it's IsSpacing* method invocations. Profile from following feedback ticket showed ~100ms time spent doing these allocations: https://developercommunity.visualstudio.com/content/problem/1006207/vs-2019-constant-freezing-please-wait-for-an-edito.html?childToView=1065769
This commit is contained in:
parent
c329dc555a
commit
da52d6b636
|
|
@ -16,27 +16,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
'@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*'
|
'@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Following four high traffic methods cached as using method groups would cause allocation on every invocation.
|
|
||||||
protected static readonly Func<SyntaxToken, bool> IsSpacingToken = (token) =>
|
|
||||||
{
|
|
||||||
return token.Kind == SyntaxKind.Whitespace;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected static readonly Func<SyntaxToken, bool> IsSpacingTokenIncludingNewLines = (token) =>
|
|
||||||
{
|
|
||||||
return IsSpacingToken(token) || token.Kind == SyntaxKind.NewLine;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected static readonly Func<SyntaxToken, bool> IsSpacingTokenIncludingComments = (token) =>
|
|
||||||
{
|
|
||||||
return IsSpacingToken(token) || token.Kind == SyntaxKind.CSharpComment;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected static readonly Func<SyntaxToken, bool> IsSpacingTokenIncludingNewLinesAndComments = (token) =>
|
|
||||||
{
|
|
||||||
return IsSpacingTokenIncludingNewLines(token) || token.Kind == SyntaxKind.CSharpComment;
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly Func<SyntaxToken, bool> IsValidStatementSpacingToken =
|
private static readonly Func<SyntaxToken, bool> IsValidStatementSpacingToken =
|
||||||
IsSpacingTokenIncludingNewLinesAndComments;
|
IsSpacingTokenIncludingNewLinesAndComments;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: true));
|
AcceptWhile(IsSpacingTokenIncludingNewLines);
|
||||||
builder.Add(OutputAsMarkupLiteral());
|
builder.Add(OutputAsMarkupLiteral());
|
||||||
|
|
||||||
if (At(SyntaxKind.OpenAngle))
|
if (At(SyntaxKind.OpenAngle))
|
||||||
|
|
@ -683,7 +683,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var bookmark = CurrentStart.AbsoluteIndex;
|
var bookmark = CurrentStart.AbsoluteIndex;
|
||||||
|
|
||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
ReadWhile(IsSpacingToken(includeNewLines: true));
|
ReadWhile(IsSpacingTokenIncludingNewLines);
|
||||||
|
|
||||||
// Open Angle
|
// Open Angle
|
||||||
if (At(SyntaxKind.OpenAngle) && NextIs(SyntaxKind.ForwardSlash))
|
if (At(SyntaxKind.OpenAngle) && NextIs(SyntaxKind.ForwardSlash))
|
||||||
|
|
@ -754,7 +754,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
SyntaxToken forwardSlashToken = null;
|
SyntaxToken forwardSlashToken = null;
|
||||||
SyntaxToken closeAngleToken = null;
|
SyntaxToken closeAngleToken = null;
|
||||||
|
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: false));
|
AcceptWhile(IsSpacingToken);
|
||||||
miscAttributeContentBuilder.Add(OutputAsMarkupLiteral());
|
miscAttributeContentBuilder.Add(OutputAsMarkupLiteral());
|
||||||
|
|
||||||
if (At(SyntaxKind.CloseAngle) ||
|
if (At(SyntaxKind.CloseAngle) ||
|
||||||
|
|
@ -1442,7 +1442,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
private void ParseDoubleTransition(in SyntaxListBuilder<RazorSyntaxNode> builder)
|
private void ParseDoubleTransition(in SyntaxListBuilder<RazorSyntaxNode> builder)
|
||||||
{
|
{
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: true));
|
AcceptWhile(IsSpacingTokenIncludingNewLines);
|
||||||
builder.Add(OutputAsMarkupLiteral());
|
builder.Add(OutputAsMarkupLiteral());
|
||||||
|
|
||||||
// First transition
|
// First transition
|
||||||
|
|
@ -1463,7 +1463,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
// We don't want to write it to output.
|
// We don't want to write it to output.
|
||||||
Context.NullGenerateWhitespaceAndNewLine = false;
|
Context.NullGenerateWhitespaceAndNewLine = false;
|
||||||
SpanContext.ChunkGenerator = SpanChunkGenerator.Null;
|
SpanContext.ChunkGenerator = SpanChunkGenerator.Null;
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: false));
|
AcceptWhile(IsSpacingToken);
|
||||||
if (At(SyntaxKind.NewLine))
|
if (At(SyntaxKind.NewLine))
|
||||||
{
|
{
|
||||||
AcceptAndMoveNext();
|
AcceptAndMoveNext();
|
||||||
|
|
@ -1549,7 +1549,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
// We don't want to write it to output.
|
// We don't want to write it to output.
|
||||||
Context.NullGenerateWhitespaceAndNewLine = false;
|
Context.NullGenerateWhitespaceAndNewLine = false;
|
||||||
SpanContext.ChunkGenerator = SpanChunkGenerator.Null;
|
SpanContext.ChunkGenerator = SpanChunkGenerator.Null;
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: false));
|
AcceptWhile(IsSpacingToken);
|
||||||
if (At(SyntaxKind.NewLine))
|
if (At(SyntaxKind.NewLine))
|
||||||
{
|
{
|
||||||
AcceptAndMoveNext();
|
AcceptAndMoveNext();
|
||||||
|
|
@ -1596,7 +1596,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
(At(SyntaxKind.NewLine) ||
|
(At(SyntaxKind.NewLine) ||
|
||||||
(At(SyntaxKind.Whitespace) && NextIs(SyntaxKind.NewLine))))
|
(At(SyntaxKind.Whitespace) && NextIs(SyntaxKind.NewLine))))
|
||||||
{
|
{
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: false));
|
AcceptWhile(IsSpacingToken);
|
||||||
AcceptAndMoveNext();
|
AcceptAndMoveNext();
|
||||||
SpanContext.ChunkGenerator = SpanChunkGenerator.Null;
|
SpanContext.ChunkGenerator = SpanChunkGenerator.Null;
|
||||||
builder.Add(OutputAsMarkupEphemeralLiteral());
|
builder.Add(OutputAsMarkupEphemeralLiteral());
|
||||||
|
|
@ -1611,7 +1611,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
// We don't want to write it to output.
|
// We don't want to write it to output.
|
||||||
Context.NullGenerateWhitespaceAndNewLine = false;
|
Context.NullGenerateWhitespaceAndNewLine = false;
|
||||||
SpanContext.ChunkGenerator = SpanChunkGenerator.Null;
|
SpanContext.ChunkGenerator = SpanChunkGenerator.Null;
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: false));
|
AcceptWhile(IsSpacingToken);
|
||||||
if (At(SyntaxKind.NewLine))
|
if (At(SyntaxKind.NewLine))
|
||||||
{
|
{
|
||||||
AcceptAndMoveNext();
|
AcceptAndMoveNext();
|
||||||
|
|
@ -1620,7 +1620,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
builder.Add(OutputAsMarkupEphemeralLiteral());
|
builder.Add(OutputAsMarkupEphemeralLiteral());
|
||||||
}
|
}
|
||||||
|
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: true));
|
AcceptWhile(IsSpacingTokenIncludingNewLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ScriptTagExpectsHtml(MarkupStartTagSyntax tagBlock)
|
private bool ScriptTagExpectsHtml(MarkupStartTagSyntax tagBlock)
|
||||||
|
|
@ -2111,11 +2111,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Func<SyntaxToken, bool> IsSpacingToken(bool includeNewLines)
|
|
||||||
{
|
|
||||||
return token => token.Kind == SyntaxKind.Whitespace || (includeNewLines && token.Kind == SyntaxKind.NewLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool IsHyphen(SyntaxToken token)
|
internal static bool IsHyphen(SyntaxToken token)
|
||||||
{
|
{
|
||||||
return token.Kind == SyntaxKind.Text && token.Content == "-";
|
return token.Kind == SyntaxKind.Text && token.Content == "-";
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
private readonly TokenizerView<TTokenizer> _tokenizer;
|
private readonly TokenizerView<TTokenizer> _tokenizer;
|
||||||
private SyntaxListBuilder<SyntaxToken>? _tokenBuilder;
|
private SyntaxListBuilder<SyntaxToken>? _tokenBuilder;
|
||||||
|
|
||||||
|
// Following four high traffic methods cached as using method groups would cause allocation on every invocation.
|
||||||
|
protected static readonly Func<SyntaxToken, bool> IsSpacingToken = (token) =>
|
||||||
|
{
|
||||||
|
return token.Kind == SyntaxKind.Whitespace;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected static readonly Func<SyntaxToken, bool> IsSpacingTokenIncludingNewLines = (token) =>
|
||||||
|
{
|
||||||
|
return IsSpacingToken(token) || token.Kind == SyntaxKind.NewLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected static readonly Func<SyntaxToken, bool> IsSpacingTokenIncludingComments = (token) =>
|
||||||
|
{
|
||||||
|
return IsSpacingToken(token) || token.Kind == SyntaxKind.CSharpComment;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected static readonly Func<SyntaxToken, bool> IsSpacingTokenIncludingNewLinesAndComments = (token) =>
|
||||||
|
{
|
||||||
|
return IsSpacingTokenIncludingNewLines(token) || token.Kind == SyntaxKind.CSharpComment;
|
||||||
|
};
|
||||||
|
|
||||||
protected TokenizerBackedParser(LanguageCharacteristics<TTokenizer> language, ParserContext context)
|
protected TokenizerBackedParser(LanguageCharacteristics<TTokenizer> language, ParserContext context)
|
||||||
: base(context)
|
: base(context)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue