From ffdf5d2827c0b5d9087a583d90c703f5df6c389c Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Thu, 14 Jan 2016 16:15:27 -0800 Subject: [PATCH] Remove allocations from lookahead This makes lookahead allocation-free, saving about 15MB in our current benchmark. --- .../Text/LookaheadToken.cs | 21 +++++++++---------- .../Text/TextExtensions.cs | 5 +---- .../Tokenizer/Tokenizer.cs | 4 ++-- .../Tokenizer/TokenizerLookaheadTest.cs | 2 +- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.AspNet.Razor/Text/LookaheadToken.cs b/src/Microsoft.AspNet.Razor/Text/LookaheadToken.cs index 063c5f95fb..f50e0880dc 100644 --- a/src/Microsoft.AspNet.Razor/Text/LookaheadToken.cs +++ b/src/Microsoft.AspNet.Razor/Text/LookaheadToken.cs @@ -5,14 +5,19 @@ using System; namespace Microsoft.AspNet.Razor.Text { - public class LookaheadToken : IDisposable + public struct LookaheadToken : IDisposable { - private Action _cancelAction; + private readonly ITextBuffer _buffer; + private readonly int _position; + private bool _accepted; - public LookaheadToken(Action cancelAction) + public LookaheadToken(ITextBuffer buffer) { - _cancelAction = cancelAction; + _buffer = buffer; + _position = buffer.Position; + + _accepted = false; } public void Accept() @@ -21,16 +26,10 @@ namespace Microsoft.AspNet.Razor.Text } public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) { if (!_accepted) { - _cancelAction(); + _buffer.Position = _position; } } } diff --git a/src/Microsoft.AspNet.Razor/Text/TextExtensions.cs b/src/Microsoft.AspNet.Razor/Text/TextExtensions.cs index 265ae7ba3c..b1693445d0 100644 --- a/src/Microsoft.AspNet.Razor/Text/TextExtensions.cs +++ b/src/Microsoft.AspNet.Razor/Text/TextExtensions.cs @@ -25,10 +25,7 @@ namespace Microsoft.AspNet.Razor.Text public static LookaheadToken BeginLookahead(this ITextBuffer self) { var start = self.Position; - return new LookaheadToken(() => - { - self.Position = start; - }); + return new LookaheadToken(self); } public static string ReadToEnd(this ITextBuffer self) diff --git a/src/Microsoft.AspNet.Razor/Tokenizer/Tokenizer.cs b/src/Microsoft.AspNet.Razor/Tokenizer/Tokenizer.cs index 9b23e855a9..62a8f903de 100644 --- a/src/Microsoft.AspNet.Razor/Tokenizer/Tokenizer.cs +++ b/src/Microsoft.AspNet.Razor/Tokenizer/Tokenizer.cs @@ -165,7 +165,7 @@ namespace Microsoft.AspNet.Razor.Tokenizer protected char Peek() { - using (LookaheadToken lookahead = Source.BeginLookahead()) + using (var lookahead = Source.BeginLookahead()) { MoveNext(); return CurrentCharacter; @@ -250,7 +250,7 @@ namespace Microsoft.AspNet.Razor.Tokenizer oldBuffer = Buffer.ToString(); } - using (LookaheadToken lookahead = Source.BeginLookahead()) + using (var lookahead = Source.BeginLookahead()) { for (int i = 0; i < expected.Length; i++) { diff --git a/test/Microsoft.AspNet.Razor.Test/Tokenizer/TokenizerLookaheadTest.cs b/test/Microsoft.AspNet.Razor.Test/Tokenizer/TokenizerLookaheadTest.cs index a3292f7e7e..17d4850df4 100644 --- a/test/Microsoft.AspNet.Razor.Test/Tokenizer/TokenizerLookaheadTest.cs +++ b/test/Microsoft.AspNet.Razor.Test/Tokenizer/TokenizerLookaheadTest.cs @@ -78,7 +78,7 @@ namespace Microsoft.AspNet.Razor.Test.Tokenizer public void After_Accepting_Lookahead_Tokenizer_Returns_Next_Token() { var tokenizer = new HtmlTokenizer(new SeekableTextReader(new StringReader(""))); - using (LookaheadToken lookahead = tokenizer.Source.BeginLookahead()) + using (var lookahead = tokenizer.Source.BeginLookahead()) { Assert.Equal(new HtmlSymbol(0, 0, 0, "<", HtmlSymbolType.OpenAngle), tokenizer.NextSymbol()); Assert.Equal(new HtmlSymbol(1, 0, 1, "foo", HtmlSymbolType.Text), tokenizer.NextSymbol());