Improve CSharpLanguageCharacteristics.MapKeyword performance (dotnet/aspnetcore-tooling#1879)
* Improve CSharpLanguageCharacteristics.MapKeyword performance
The razor typing perf test profile I'm looking at has 156 ms of CPU cycles spent in this method, mostly in Enum.ToString()
\n\nCommit migrated from e821a4642e
This commit is contained in:
parent
a70de6b67b
commit
016fd1ee9e
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
|
||||
|
|
@ -9,8 +10,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
internal class CSharpLanguageCharacteristics : LanguageCharacteristics<CSharpTokenizer>
|
||||
{
|
||||
private static readonly CSharpLanguageCharacteristics _instance = new CSharpLanguageCharacteristics();
|
||||
|
||||
private static Dictionary<SyntaxKind, string> _tokenSamples = new Dictionary<SyntaxKind, string>()
|
||||
{
|
||||
{ SyntaxKind.Arrow, "->" },
|
||||
|
|
@ -64,8 +63,108 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{ SyntaxKind.Transition, "@" },
|
||||
};
|
||||
|
||||
// Allows performance optimization of GetKeyword such that it need not do Enum.ToString
|
||||
private static IReadOnlyDictionary<CSharpKeyword, string> _keywordNames = new Dictionary<CSharpKeyword, string>()
|
||||
{
|
||||
{ CSharpKeyword.Await, "await" },
|
||||
{ CSharpKeyword.Abstract, "abstract" },
|
||||
{ CSharpKeyword.Byte, "byte" },
|
||||
{ CSharpKeyword.Class, "class" },
|
||||
{ CSharpKeyword.Delegate, "delegate" },
|
||||
{ CSharpKeyword.Event, "event" },
|
||||
{ CSharpKeyword.Fixed, "fixed" },
|
||||
{ CSharpKeyword.If, "if" },
|
||||
{ CSharpKeyword.Internal, "internal" },
|
||||
{ CSharpKeyword.New, "new" },
|
||||
{ CSharpKeyword.Override, "override" },
|
||||
{ CSharpKeyword.Readonly, "readonly" },
|
||||
{ CSharpKeyword.Short, "short" },
|
||||
{ CSharpKeyword.Struct, "struct" },
|
||||
{ CSharpKeyword.Try, "try" },
|
||||
{ CSharpKeyword.Unsafe, "unsafe" },
|
||||
{ CSharpKeyword.Volatile, "volatile" },
|
||||
{ CSharpKeyword.As, "as" },
|
||||
{ CSharpKeyword.Do, "do" },
|
||||
{ CSharpKeyword.Is, "is" },
|
||||
{ CSharpKeyword.Params, "params" },
|
||||
{ CSharpKeyword.Ref, "ref" },
|
||||
{ CSharpKeyword.Switch, "switch" },
|
||||
{ CSharpKeyword.Ushort, "ushort" },
|
||||
{ CSharpKeyword.While, "while" },
|
||||
{ CSharpKeyword.Case, "case" },
|
||||
{ CSharpKeyword.Const, "const" },
|
||||
{ CSharpKeyword.Explicit, "explicit" },
|
||||
{ CSharpKeyword.Float, "float" },
|
||||
{ CSharpKeyword.Null, "null" },
|
||||
{ CSharpKeyword.Sizeof, "sizeof" },
|
||||
{ CSharpKeyword.Typeof, "typeof" },
|
||||
{ CSharpKeyword.Implicit, "implicit" },
|
||||
{ CSharpKeyword.Private, "private" },
|
||||
{ CSharpKeyword.This, "this" },
|
||||
{ CSharpKeyword.Using, "using" },
|
||||
{ CSharpKeyword.Extern, "extern" },
|
||||
{ CSharpKeyword.Return, "return" },
|
||||
{ CSharpKeyword.Stackalloc, "stackalloc" },
|
||||
{ CSharpKeyword.Uint, "uint" },
|
||||
{ CSharpKeyword.Base, "base" },
|
||||
{ CSharpKeyword.Catch, "catch" },
|
||||
{ CSharpKeyword.Continue, "continue" },
|
||||
{ CSharpKeyword.Double, "double" },
|
||||
{ CSharpKeyword.For, "for" },
|
||||
{ CSharpKeyword.In, "in" },
|
||||
{ CSharpKeyword.Lock, "lock" },
|
||||
{ CSharpKeyword.Object, "object" },
|
||||
{ CSharpKeyword.Protected, "protected" },
|
||||
{ CSharpKeyword.Static, "static" },
|
||||
{ CSharpKeyword.False, "false" },
|
||||
{ CSharpKeyword.Public, "public" },
|
||||
{ CSharpKeyword.Sbyte, "sbyte" },
|
||||
{ CSharpKeyword.Throw, "throw" },
|
||||
{ CSharpKeyword.Virtual, "virtual" },
|
||||
{ CSharpKeyword.Decimal, "decimal" },
|
||||
{ CSharpKeyword.Else, "else" },
|
||||
{ CSharpKeyword.Operator, "operator" },
|
||||
{ CSharpKeyword.String, "string" },
|
||||
{ CSharpKeyword.Ulong, "ulong" },
|
||||
{ CSharpKeyword.Bool, "bool" },
|
||||
{ CSharpKeyword.Char, "char" },
|
||||
{ CSharpKeyword.Default, "default" },
|
||||
{ CSharpKeyword.Foreach, "foreach" },
|
||||
{ CSharpKeyword.Long, "long" },
|
||||
{ CSharpKeyword.Void, "void" },
|
||||
{ CSharpKeyword.Enum, "enum" },
|
||||
{ CSharpKeyword.Finally, "finally" },
|
||||
{ CSharpKeyword.Int, "int" },
|
||||
{ CSharpKeyword.Out, "out" },
|
||||
{ CSharpKeyword.Sealed, "sealed" },
|
||||
{ CSharpKeyword.True, "true" },
|
||||
{ CSharpKeyword.Goto, "goto" },
|
||||
{ CSharpKeyword.Unchecked, "unchecked" },
|
||||
{ CSharpKeyword.Interface, "interface" },
|
||||
{ CSharpKeyword.Break, "break" },
|
||||
{ CSharpKeyword.Checked, "checked" },
|
||||
{ CSharpKeyword.Namespace, "namespace" },
|
||||
{ CSharpKeyword.When, "when" },
|
||||
};
|
||||
|
||||
private static readonly CSharpLanguageCharacteristics _instance = new CSharpLanguageCharacteristics();
|
||||
|
||||
protected CSharpLanguageCharacteristics()
|
||||
{
|
||||
#if DEBUG
|
||||
var values = Enum.GetValues(typeof(CSharpKeyword));
|
||||
|
||||
Debug.Assert(values.Length == _keywordNames.Count, "_keywordNames and CSharpKeyword are out of sync");
|
||||
for (var i = 0; i < values.Length; i++)
|
||||
{
|
||||
var keyword = (CSharpKeyword) values.GetValue(i);
|
||||
|
||||
var expectedValue = keyword.ToString().ToLowerInvariant();
|
||||
var actualValue = _keywordNames[keyword];
|
||||
|
||||
Debug.Assert(expectedValue == actualValue, "_keywordNames and CSharpKeyword are out of sync for " + expectedValue);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static CSharpLanguageCharacteristics Instance => _instance;
|
||||
|
|
@ -170,7 +269,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
public static string GetKeyword(CSharpKeyword keyword)
|
||||
{
|
||||
return keyword.ToString().ToLowerInvariant();
|
||||
if (!_keywordNames.TryGetValue(keyword, out var value))
|
||||
{
|
||||
value = keyword.ToString().ToLowerInvariant();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue