Small perf improvement in TokenizerBackedParser.Accept and ReadWhile. (dotnet/aspnetcore-tooling#1882)
In the razor perf typing test, Accept was showing 27 ms allocating enumerators. Additionally, modified ReadWhile to only allocate if it would return a non-empty collection (and to not use the complexity introduced by using yield enumerators)\n\nCommit migrated from 27a14af36a
This commit is contained in:
parent
485924edd2
commit
a70de6b67b
|
|
@ -893,7 +893,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
}
|
||||
}
|
||||
|
||||
protected bool TryParseDirective(in SyntaxListBuilder<RazorSyntaxNode> builder, IEnumerable<SyntaxToken> whitespace, CSharpTransitionSyntax transition, string directive)
|
||||
protected bool TryParseDirective(in SyntaxListBuilder<RazorSyntaxNode> builder, IReadOnlyList<SyntaxToken> whitespace, CSharpTransitionSyntax transition, string directive)
|
||||
{
|
||||
if (_directiveParserMap.TryGetValue(directive, out var handler))
|
||||
{
|
||||
|
|
@ -1679,7 +1679,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
}
|
||||
}
|
||||
|
||||
private bool TryParseKeyword(in SyntaxListBuilder<RazorSyntaxNode> builder, IEnumerable<SyntaxToken> whitespace, CSharpTransitionSyntax transition)
|
||||
private bool TryParseKeyword(in SyntaxListBuilder<RazorSyntaxNode> builder, IReadOnlyList<SyntaxToken> whitespace, CSharpTransitionSyntax transition)
|
||||
{
|
||||
var result = CSharpTokenizer.GetTokenKeyword(CurrentToken);
|
||||
Debug.Assert(CurrentToken.Kind == SyntaxKind.Keyword && result.HasValue);
|
||||
|
|
@ -2387,7 +2387,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<SyntaxToken> SkipToNextImportantToken(in SyntaxListBuilder<RazorSyntaxNode> builder)
|
||||
private IReadOnlyList<SyntaxToken> SkipToNextImportantToken(in SyntaxListBuilder<RazorSyntaxNode> builder)
|
||||
{
|
||||
while (!EndOfFile)
|
||||
{
|
||||
|
|
@ -2406,7 +2406,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return whitespace;
|
||||
}
|
||||
}
|
||||
return Enumerable.Empty<SyntaxToken>();
|
||||
return Array.Empty<SyntaxToken>();
|
||||
}
|
||||
|
||||
private void DefaultSpanContextConfig(SpanContextBuilder spanContext)
|
||||
|
|
|
|||
|
|
@ -1085,9 +1085,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
}
|
||||
}
|
||||
|
||||
private bool TryParseAttributeName(out IEnumerable<SyntaxToken> nameTokens)
|
||||
private bool TryParseAttributeName(out IReadOnlyList<SyntaxToken> nameTokens)
|
||||
{
|
||||
nameTokens = Enumerable.Empty<SyntaxToken>();
|
||||
nameTokens = Array.Empty<SyntaxToken>();
|
||||
//
|
||||
// We are currently here <input |name="..." />
|
||||
// If we encounter a transition (@) here, it can be parsed as CSharp or Markup depending on the feature flag.
|
||||
|
|
|
|||
|
|
@ -266,14 +266,22 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return true;
|
||||
}
|
||||
|
||||
protected internal IEnumerable<SyntaxToken> ReadWhile(params SyntaxKind[] types)
|
||||
protected internal IReadOnlyList<SyntaxToken> ReadWhile(Func<SyntaxToken, bool> condition)
|
||||
{
|
||||
return ReadWhile(token => types.Any(expected => expected == token.Kind));
|
||||
}
|
||||
if (!EnsureCurrent() || !condition(CurrentToken))
|
||||
{
|
||||
return Array.Empty<SyntaxToken>();
|
||||
}
|
||||
|
||||
var result = new List<SyntaxToken>();
|
||||
do
|
||||
{
|
||||
result.Add(CurrentToken);
|
||||
NextToken();
|
||||
}
|
||||
while (EnsureCurrent() && condition(CurrentToken));
|
||||
|
||||
protected internal IEnumerable<SyntaxToken> ReadWhile(Func<SyntaxToken, bool> condition)
|
||||
{
|
||||
return ReadWhileLazy(condition).ToList();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected bool AtIdentifier(bool allowKeywords)
|
||||
|
|
@ -283,17 +291,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
(allowKeywords && Language.IsKeyword(CurrentToken)));
|
||||
}
|
||||
|
||||
// Don't open this to sub classes because it's lazy but it looks eager.
|
||||
// You have to advance the Enumerable to read the next characters.
|
||||
internal IEnumerable<SyntaxToken> ReadWhileLazy(Func<SyntaxToken, bool> condition)
|
||||
{
|
||||
while (EnsureCurrent() && condition(CurrentToken))
|
||||
{
|
||||
yield return CurrentToken;
|
||||
NextToken();
|
||||
}
|
||||
}
|
||||
|
||||
protected RazorCommentBlockSyntax ParseRazorComment()
|
||||
{
|
||||
if (!Language.KnowsTokenType(KnownTokenType.CommentStart) ||
|
||||
|
|
@ -430,13 +427,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
protected internal void AcceptWhile(Func<SyntaxToken, bool> condition)
|
||||
{
|
||||
Accept(ReadWhileLazy(condition));
|
||||
Accept(ReadWhile(condition));
|
||||
}
|
||||
|
||||
protected internal void Accept(IEnumerable<SyntaxToken> tokens)
|
||||
protected internal void Accept(IReadOnlyList<SyntaxToken> tokens)
|
||||
{
|
||||
foreach (var token in tokens)
|
||||
for(int i = 0; i < tokens.Count; i++)
|
||||
{
|
||||
var token = tokens[i];
|
||||
Accept(token);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue