Fix for #90 - removing Enum.HasFlags

This is a perf improvement of about 500ms for our razor code generation
benchmark on my dev box. That's about .8% of the overall execution time of
this benchmark.

This change will remove a bunch of unnessary allocations from the
parsing/code-generation path, and should improve responsiveness.

For reference Enum.HasFlags performs boxing of the enum value, and then
does a type comparison to see if the types are the same. This is
significantly more costly than a normal bitwise and comparison, and it
results in allocations.
This commit is contained in:
Ryan Nowak 2014-09-18 12:44:41 -07:00
parent 2d9b3dd4fb
commit 131c973853
4 changed files with 26 additions and 26 deletions

View File

@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Razor.Editor
}
// If the change is accepted then apply the change
if (result.HasFlag(PartialParseResult.Accepted))
if ((result & PartialParseResult.Accepted) == PartialParseResult.Accepted)
{
return new EditResult(result, UpdateSpan(target, normalized));
}

View File

@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Razor.Parser
TSymbolType right = Language.FlipBracket(left);
SourceLocation start = CurrentLocation;
AcceptAndMoveNext();
if (EndOfFile && !mode.HasFlag(BalancingModes.NoErrorOnFailure))
if (EndOfFile && ((mode & BalancingModes.NoErrorOnFailure) != BalancingModes.NoErrorOnFailure))
{
Context.OnError(start,
RazorResources.FormatParseError_Expected_CloseBracket_Before_EOF(
@ -91,8 +91,8 @@ namespace Microsoft.AspNet.Razor.Parser
do
{
if (IsAtEmbeddedTransition(
mode.HasFlag(BalancingModes.AllowCommentsAndTemplates),
mode.HasFlag(BalancingModes.AllowEmbeddedTransitions)))
(mode & BalancingModes.AllowCommentsAndTemplates) == BalancingModes.AllowCommentsAndTemplates,
(mode & BalancingModes.AllowEmbeddedTransitions) == BalancingModes.AllowEmbeddedTransitions))
{
Accept(syms);
syms.Clear();
@ -118,14 +118,14 @@ namespace Microsoft.AspNet.Razor.Parser
if (nesting > 0)
{
if (!mode.HasFlag(BalancingModes.NoErrorOnFailure))
if ((mode & BalancingModes.NoErrorOnFailure) != BalancingModes.NoErrorOnFailure)
{
Context.OnError(start,
RazorResources.FormatParseError_Expected_CloseBracket_Before_EOF(
Language.GetSample(left),
Language.GetSample(right)));
}
if (mode.HasFlag(BalancingModes.BacktrackOnFailure))
if ((mode & BalancingModes.BacktrackOnFailure) == BalancingModes.BacktrackOnFailure)
{
Context.Source.Position = startPosition;
NextToken();

View File

@ -60,12 +60,12 @@ namespace Microsoft.AspNet.Razor
treeBuilder.AppendLine();
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Partial Parse Result: {0}", result);
treeBuilder.AppendLine();
if (result.HasFlag(PartialParseResult.Rejected))
if ((result & PartialParseResult.Rejected) == PartialParseResult.Rejected)
{
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Tree Structure Changed: {0}", treeStructureChanged);
treeBuilder.AppendLine();
}
if (result.HasFlag(PartialParseResult.AutoCompleteBlock))
if ((result & PartialParseResult.AutoCompleteBlock) == PartialParseResult.AutoCompleteBlock)
{
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Auto Complete Insert String: \"{0}\"", parser.GetAutoCompleteString());
treeBuilder.AppendLine();

View File

@ -156,13 +156,13 @@ namespace Microsoft.AspNet.Razor
}
// If partial parsing failed or there were outstanding parser tasks, start a full reparse
if (result.HasFlag(PartialParseResult.Rejected))
if ((result & PartialParseResult.Rejected) == PartialParseResult.Rejected)
{
_parser.QueueChange(change);
}
// Otherwise, remember if this was provisionally accepted for next partial parse
LastResultProvisional = result.HasFlag(PartialParseResult.Provisional);
LastResultProvisional = (result & PartialParseResult.Provisional) == PartialParseResult.Provisional;
VerifyFlagsAreValid(result);
#if EDITOR_TRACING
@ -172,8 +172,8 @@ namespace Microsoft.AspNet.Razor
#endif
RazorEditorTrace.TraceLine(
RazorResources.FormatTrace_EditorProcessedChange(
Path.GetFileName(FileName),
changeString, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?",
Path.GetFileName(FileName),
changeString, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?",
result.ToString()));
return result;
}
@ -206,7 +206,7 @@ namespace Microsoft.AspNet.Razor
{
EditResult editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
result = editResult.Result;
if (!editResult.Result.HasFlag(PartialParseResult.Rejected))
if ((editResult.Result & PartialParseResult.Rejected) != PartialParseResult.Rejected)
{
_lastChangeOwner.ReplaceWith(editResult.EditedSpan);
}
@ -224,13 +224,13 @@ namespace Microsoft.AspNet.Razor
}
else if (_lastChangeOwner != null)
{
EditResult editRes = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
result = editRes.Result;
if (!editRes.Result.HasFlag(PartialParseResult.Rejected))
EditResult editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
result = editResult.Result;
if ((editResult.Result & PartialParseResult.Rejected) != PartialParseResult.Rejected)
{
_lastChangeOwner.ReplaceWith(editRes.EditedSpan);
_lastChangeOwner.ReplaceWith(editResult.EditedSpan);
}
if (result.HasFlag(PartialParseResult.AutoCompleteBlock))
if ((result & PartialParseResult.AutoCompleteBlock) == PartialParseResult.AutoCompleteBlock)
{
_lastAutoCompleteSpan = _lastChangeOwner;
}
@ -269,17 +269,17 @@ namespace Microsoft.AspNet.Razor
[Conditional("DEBUG")]
private static void VerifyFlagsAreValid(PartialParseResult result)
{
Debug.Assert(result.HasFlag(PartialParseResult.Accepted) ||
result.HasFlag(PartialParseResult.Rejected),
Debug.Assert(((result & PartialParseResult.Accepted) == PartialParseResult.Accepted) ||
((result & PartialParseResult.Rejected) == PartialParseResult.Rejected),
"Partial Parse result does not have either of Accepted or Rejected flags set");
Debug.Assert(result.HasFlag(PartialParseResult.Rejected) ||
!result.HasFlag(PartialParseResult.SpanContextChanged),
Debug.Assert(((result & PartialParseResult.Rejected) == PartialParseResult.Rejected) ||
((result & PartialParseResult.SpanContextChanged) != PartialParseResult.SpanContextChanged),
"Partial Parse result was Accepted AND had SpanContextChanged flag set");
Debug.Assert(result.HasFlag(PartialParseResult.Rejected) ||
!result.HasFlag(PartialParseResult.AutoCompleteBlock),
Debug.Assert(((result & PartialParseResult.Rejected) == PartialParseResult.Rejected) ||
((result & PartialParseResult.AutoCompleteBlock) != PartialParseResult.AutoCompleteBlock),
"Partial Parse result was Accepted AND had AutoCompleteBlock flag set");
Debug.Assert(result.HasFlag(PartialParseResult.Accepted) ||
!result.HasFlag(PartialParseResult.Provisional),
Debug.Assert(((result & PartialParseResult.Accepted) == PartialParseResult.Accepted) ||
((result & PartialParseResult.Provisional) != PartialParseResult.Provisional),
"Partial Parse result was Rejected AND had Provisional flag set");
}
}