Skip to content

Commit 6b6280f

Browse files
authored
Attempt some low hanging perf optimizations in Razor (dotnet#32950)
* Attempt some low hanging perf optimizations * Use char.IsLetter / char.IsDigit etc to optimize for latin text * Remove some expensive virtual calls
1 parent 1e3c70b commit 6b6280f

File tree

2 files changed

+16
-48
lines changed

2 files changed

+16
-48
lines changed

src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/ParserHelpers.cs

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Globalization;
77
using System.Linq;
8+
using System.Runtime.CompilerServices;
89

910
namespace Microsoft.AspNetCore.Razor.Language.Legacy
1011
{
@@ -55,28 +56,9 @@ public static bool IsIdentifierStart(char value)
5556

5657
public static bool IsIdentifierPart(char value)
5758
{
58-
return IsLetter(value)
59-
|| IsDecimalDigit(value)
60-
|| IsConnecting(value)
61-
|| IsCombining(value)
62-
|| IsFormatting(value);
63-
}
64-
65-
public static bool IsFormatting(char value)
66-
{
67-
return CharUnicodeInfo.GetUnicodeCategory(value) == UnicodeCategory.Format;
68-
}
69-
70-
public static bool IsCombining(char value)
71-
{
72-
var cat = CharUnicodeInfo.GetUnicodeCategory(value);
73-
74-
return cat == UnicodeCategory.SpacingCombiningMark || cat == UnicodeCategory.NonSpacingMark;
75-
}
76-
77-
public static bool IsConnecting(char value)
78-
{
79-
return CharUnicodeInfo.GetUnicodeCategory(value) == UnicodeCategory.ConnectorPunctuation;
59+
return IsLetter(value) ||
60+
IsDecimalDigit(value) ||
61+
(CharUnicodeInfo.GetUnicodeCategory(value) is UnicodeCategory.Format or UnicodeCategory.SpacingCombiningMark or UnicodeCategory.NonSpacingMark or UnicodeCategory.ConnectorPunctuation);
8062
}
8163

8264
public static bool IsWhitespace(char value)
@@ -85,25 +67,14 @@ public static bool IsWhitespace(char value)
8567
value == '\f' ||
8668
value == '\t' ||
8769
value == '\u000B' || // Vertical Tab
88-
CharUnicodeInfo.GetUnicodeCategory(value) == UnicodeCategory.SpaceSeparator;
70+
char.IsSeparator(value);;
8971
}
9072

91-
public static bool IsLetter(char value)
92-
{
93-
var cat = CharUnicodeInfo.GetUnicodeCategory(value);
73+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
74+
public static bool IsLetter(char value) => char.IsLetter(value);
9475

95-
return cat == UnicodeCategory.UppercaseLetter
96-
|| cat == UnicodeCategory.LowercaseLetter
97-
|| cat == UnicodeCategory.TitlecaseLetter
98-
|| cat == UnicodeCategory.ModifierLetter
99-
|| cat == UnicodeCategory.OtherLetter
100-
|| cat == UnicodeCategory.LetterNumber;
101-
}
102-
103-
public static bool IsDecimalDigit(char value)
104-
{
105-
return CharUnicodeInfo.GetUnicodeCategory(value) == UnicodeCategory.DecimalDigitNumber;
106-
}
76+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
77+
public static bool IsDecimalDigit(char value) => char.IsDigit(value);
10778

10879
// From http://dev.w3.org/html5/spec/Overview.html#elements-0
10980
public static readonly HashSet<string> VoidElements = new HashSet<string>(StringComparer.OrdinalIgnoreCase)

src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/SeekableTextReader.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88

99
namespace Microsoft.AspNetCore.Razor.Language.Legacy
1010
{
11-
internal class SeekableTextReader : TextReader, ITextDocument
11+
internal sealed class SeekableTextReader : TextReader, ITextDocument
1212
{
1313
private readonly RazorSourceDocument _sourceDocument;
14+
private readonly string _filePath;
1415
private int _position;
1516
private int _current;
1617
private SourceLocation _location;
@@ -20,12 +21,8 @@ internal class SeekableTextReader : TextReader, ITextDocument
2021

2122
public SeekableTextReader(RazorSourceDocument source)
2223
{
23-
if (source == null)
24-
{
25-
throw new ArgumentNullException(nameof(source));
26-
}
27-
2824
_sourceDocument = source;
25+
_filePath = source.FilePath;
2926
_cachedLineInfo = (new TextSpan(0, _sourceDocument.Lines.GetLineLength(0)), 0);
3027
UpdateState();
3128
}
@@ -61,7 +58,7 @@ private void UpdateState()
6158
{
6259
if (_cachedLineInfo.Span.Contains(_position))
6360
{
64-
_location = new SourceLocation(_sourceDocument.FilePath, _position, _cachedLineInfo.LineIndex, _position - _cachedLineInfo.Span.Start);
61+
_location = new SourceLocation(_filePath, _position, _cachedLineInfo.LineIndex, _position - _cachedLineInfo.Span.Start);
6562
_current = _sourceDocument[_location.AbsoluteIndex];
6663

6764
return;
@@ -79,7 +76,7 @@ private void UpdateState()
7976
if (nextLineSpan.Contains(_position))
8077
{
8178
_cachedLineInfo = (nextLineSpan, nextLineIndex);
82-
_location = new SourceLocation(_sourceDocument.FilePath, _position, nextLineIndex, _position - nextLineSpan.Start);
79+
_location = new SourceLocation(_filePath, _position, nextLineIndex, _position - nextLineSpan.Start);
8380
_current = _sourceDocument[_location.AbsoluteIndex];
8481

8582
return;
@@ -95,7 +92,7 @@ private void UpdateState()
9592
if (prevLineSpan.Contains(_position))
9693
{
9794
_cachedLineInfo = (prevLineSpan, prevLineIndex);
98-
_location = new SourceLocation(_sourceDocument.FilePath, _position, prevLineIndex, _position - prevLineSpan.Start);
95+
_location = new SourceLocation(_filePath, _position, prevLineIndex, _position - prevLineSpan.Start);
9996
_current = _sourceDocument[_location.AbsoluteIndex];
10097

10198
return;
@@ -123,7 +120,7 @@ private void UpdateState()
123120
}
124121

125122
var lineNumber = _sourceDocument.Lines.Count - 1;
126-
_location = new SourceLocation(_sourceDocument.FilePath, Length, lineNumber, _sourceDocument.Lines.GetLineLength(lineNumber));
123+
_location = new SourceLocation(_filePath, Length, lineNumber, _sourceDocument.Lines.GetLineLength(lineNumber));
127124

128125
_current = -1;
129126
}

0 commit comments

Comments
 (0)