Optimize allocations of List<ISymbol> and related
This commit is contained in:
parent
ffdf5d2827
commit
95ea4cc06f
|
|
@ -16,6 +16,7 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
|
|||
public class Span : SyntaxTreeNode
|
||||
{
|
||||
private static readonly int TypeHashCode = typeof(Span).GetHashCode();
|
||||
private string _content;
|
||||
private SourceLocation _start;
|
||||
|
||||
public Span(SpanBuilder builder)
|
||||
|
|
@ -24,7 +25,7 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
|
|||
}
|
||||
|
||||
public SpanKind Kind { get; protected set; }
|
||||
public IEnumerable<ISymbol> Symbols { get; protected set; }
|
||||
public IReadOnlyList<ISymbol> Symbols { get; protected set; }
|
||||
|
||||
// Allow test code to re-link spans
|
||||
public Span Previous { get; protected internal set; }
|
||||
|
|
@ -48,7 +49,25 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
|
|||
get { return _start; }
|
||||
}
|
||||
|
||||
public string Content { get; private set; }
|
||||
public string Content
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_content == null)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
for (var i = 0; i < Symbols.Count; i++)
|
||||
{
|
||||
var symbol = Symbols[i];
|
||||
builder.Append(symbol.Content);
|
||||
}
|
||||
|
||||
_content = builder.ToString();
|
||||
}
|
||||
|
||||
return _content;
|
||||
}
|
||||
}
|
||||
|
||||
public void Change(Action<SpanBuilder> changes)
|
||||
{
|
||||
|
|
@ -59,19 +78,15 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
|
|||
|
||||
public void ReplaceWith(SpanBuilder builder)
|
||||
{
|
||||
Debug.Assert(!builder.Symbols.Any() || builder.Symbols.All(s => s != null));
|
||||
|
||||
Kind = builder.Kind;
|
||||
Symbols = builder.Symbols;
|
||||
EditHandler = builder.EditHandler;
|
||||
ChunkGenerator = builder.ChunkGenerator ?? SpanChunkGenerator.Null;
|
||||
_start = builder.Start;
|
||||
_content = null;
|
||||
|
||||
// Since we took references to the values in SpanBuilder, clear its references out
|
||||
builder.Reset();
|
||||
|
||||
// Calculate other properties
|
||||
Content = Symbols.Aggregate(new StringBuilder(), (sb, sym) => sb.Append(sym.Content), sb => sb.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Razor.Editor;
|
||||
using Microsoft.AspNet.Razor.Chunks.Generators;
|
||||
|
|
@ -13,7 +12,7 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
|
|||
{
|
||||
public class SpanBuilder
|
||||
{
|
||||
private IList<ISymbol> _symbols = new List<ISymbol>();
|
||||
private List<ISymbol> _symbols;
|
||||
private SourceLocationTracker _tracker = new SourceLocationTracker();
|
||||
|
||||
public SpanBuilder(Span original)
|
||||
|
|
@ -31,11 +30,20 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
|
|||
}
|
||||
|
||||
public SourceLocation Start { get; set; }
|
||||
|
||||
public SpanKind Kind { get; set; }
|
||||
|
||||
public ReadOnlyCollection<ISymbol> Symbols
|
||||
public IReadOnlyList<ISymbol> Symbols
|
||||
{
|
||||
get { return new ReadOnlyCollection<ISymbol>(_symbols); }
|
||||
get
|
||||
{
|
||||
if (_symbols == null)
|
||||
{
|
||||
_symbols = new List<ISymbol>();
|
||||
}
|
||||
|
||||
return _symbols;
|
||||
}
|
||||
}
|
||||
|
||||
public SpanEditHandler EditHandler { get; set; }
|
||||
|
|
@ -43,7 +51,10 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
|
|||
|
||||
public void Reset()
|
||||
{
|
||||
_symbols = new List<ISymbol>();
|
||||
// Need to potentially allocate a new list because Span.ReplaceWith takes ownership
|
||||
// of the original list.
|
||||
_symbols = null;
|
||||
|
||||
EditHandler = SpanEditHandler.CreateDefault(s => Enumerable.Empty<ISymbol>());
|
||||
ChunkGenerator = SpanChunkGenerator.Null;
|
||||
Start = SourceLocation.Zero;
|
||||
|
|
@ -67,6 +78,11 @@ namespace Microsoft.AspNet.Razor.Parser.SyntaxTree
|
|||
return;
|
||||
}
|
||||
|
||||
if (_symbols == null)
|
||||
{
|
||||
_symbols = new List<ISymbol>();
|
||||
}
|
||||
|
||||
if (_symbols.Count == 0)
|
||||
{
|
||||
Start = symbol.Start;
|
||||
|
|
|
|||
|
|
@ -647,8 +647,9 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers.Internal
|
|||
EnsureTagBlock(tagBlock);
|
||||
|
||||
var childSpan = (Span)tagBlock.Children.First();
|
||||
|
||||
// We grab the symbol that could be forward slash
|
||||
var relevantSymbol = (HtmlSymbol)childSpan.Symbols.Take(2).Last();
|
||||
var relevantSymbol = (HtmlSymbol)childSpan.Symbols[childSpan.Symbols.Count == 1 ? 0 : 1];
|
||||
|
||||
return relevantSymbol.Type == HtmlSymbolType.ForwardSlash;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue