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 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)); return new EditResult(result, UpdateSpan(target, normalized));
} }

View File

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

View File

@ -60,12 +60,12 @@ namespace Microsoft.AspNet.Razor
treeBuilder.AppendLine(); treeBuilder.AppendLine();
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Partial Parse Result: {0}", result); treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Partial Parse Result: {0}", result);
treeBuilder.AppendLine(); treeBuilder.AppendLine();
if (result.HasFlag(PartialParseResult.Rejected)) if ((result & PartialParseResult.Rejected) == PartialParseResult.Rejected)
{ {
treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Tree Structure Changed: {0}", treeStructureChanged); treeBuilder.AppendFormat(CultureInfo.CurrentCulture, "Tree Structure Changed: {0}", treeStructureChanged);
treeBuilder.AppendLine(); 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.AppendFormat(CultureInfo.CurrentCulture, "Auto Complete Insert String: \"{0}\"", parser.GetAutoCompleteString());
treeBuilder.AppendLine(); 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 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); _parser.QueueChange(change);
} }
// Otherwise, remember if this was provisionally accepted for next partial parse // Otherwise, remember if this was provisionally accepted for next partial parse
LastResultProvisional = result.HasFlag(PartialParseResult.Provisional); LastResultProvisional = (result & PartialParseResult.Provisional) == PartialParseResult.Provisional;
VerifyFlagsAreValid(result); VerifyFlagsAreValid(result);
#if EDITOR_TRACING #if EDITOR_TRACING
@ -172,8 +172,8 @@ namespace Microsoft.AspNet.Razor
#endif #endif
RazorEditorTrace.TraceLine( RazorEditorTrace.TraceLine(
RazorResources.FormatTrace_EditorProcessedChange( RazorResources.FormatTrace_EditorProcessedChange(
Path.GetFileName(FileName), Path.GetFileName(FileName),
changeString, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?", changeString, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?",
result.ToString())); result.ToString()));
return result; return result;
} }
@ -206,7 +206,7 @@ namespace Microsoft.AspNet.Razor
{ {
EditResult editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change); EditResult editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
result = editResult.Result; result = editResult.Result;
if (!editResult.Result.HasFlag(PartialParseResult.Rejected)) if ((editResult.Result & PartialParseResult.Rejected) != PartialParseResult.Rejected)
{ {
_lastChangeOwner.ReplaceWith(editResult.EditedSpan); _lastChangeOwner.ReplaceWith(editResult.EditedSpan);
} }
@ -224,13 +224,13 @@ namespace Microsoft.AspNet.Razor
} }
else if (_lastChangeOwner != null) else if (_lastChangeOwner != null)
{ {
EditResult editRes = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change); EditResult editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
result = editRes.Result; result = editResult.Result;
if (!editRes.Result.HasFlag(PartialParseResult.Rejected)) 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; _lastAutoCompleteSpan = _lastChangeOwner;
} }
@ -269,17 +269,17 @@ namespace Microsoft.AspNet.Razor
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void VerifyFlagsAreValid(PartialParseResult result) private static void VerifyFlagsAreValid(PartialParseResult result)
{ {
Debug.Assert(result.HasFlag(PartialParseResult.Accepted) || Debug.Assert(((result & PartialParseResult.Accepted) == PartialParseResult.Accepted) ||
result.HasFlag(PartialParseResult.Rejected), ((result & PartialParseResult.Rejected) == PartialParseResult.Rejected),
"Partial Parse result does not have either of Accepted or Rejected flags set"); "Partial Parse result does not have either of Accepted or Rejected flags set");
Debug.Assert(result.HasFlag(PartialParseResult.Rejected) || Debug.Assert(((result & PartialParseResult.Rejected) == PartialParseResult.Rejected) ||
!result.HasFlag(PartialParseResult.SpanContextChanged), ((result & PartialParseResult.SpanContextChanged) != PartialParseResult.SpanContextChanged),
"Partial Parse result was Accepted AND had SpanContextChanged flag set"); "Partial Parse result was Accepted AND had SpanContextChanged flag set");
Debug.Assert(result.HasFlag(PartialParseResult.Rejected) || Debug.Assert(((result & PartialParseResult.Rejected) == PartialParseResult.Rejected) ||
!result.HasFlag(PartialParseResult.AutoCompleteBlock), ((result & PartialParseResult.AutoCompleteBlock) != PartialParseResult.AutoCompleteBlock),
"Partial Parse result was Accepted AND had AutoCompleteBlock flag set"); "Partial Parse result was Accepted AND had AutoCompleteBlock flag set");
Debug.Assert(result.HasFlag(PartialParseResult.Accepted) || Debug.Assert(((result & PartialParseResult.Accepted) == PartialParseResult.Accepted) ||
!result.HasFlag(PartialParseResult.Provisional), ((result & PartialParseResult.Provisional) != PartialParseResult.Provisional),
"Partial Parse result was Rejected AND had Provisional flag set"); "Partial Parse result was Rejected AND had Provisional flag set");
} }
} }