From f3a3dd2629489afbc0b7239b4976f95848a869a1 Mon Sep 17 00:00:00 2001 From: Boris Date: Tue, 5 Jan 2021 12:47:44 -0800 Subject: [PATCH] CSHARP-1525: JsonReader auto reset buffer --- src/MongoDB.Bson/IO/JsonBuffer.cs | 22 +++++++++++++--------- src/MongoDB.Bson/IO/JsonReader.cs | 19 +++++++++++++++++-- src/MongoDB.Bson/IO/JsonReaderSettings.cs | 15 +++++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/MongoDB.Bson/IO/JsonBuffer.cs b/src/MongoDB.Bson/IO/JsonBuffer.cs index 83b824a5e2e..4b44b1c9158 100644 --- a/src/MongoDB.Bson/IO/JsonBuffer.cs +++ b/src/MongoDB.Bson/IO/JsonBuffer.cs @@ -25,6 +25,8 @@ namespace MongoDB.Bson.IO internal class JsonBuffer { // private fields + private readonly int _readChunkSize; + private readonly int _minDiscardBufferSize; private readonly StringBuilder _buffer; private int _position; private readonly TextReader _reader; @@ -43,11 +45,11 @@ public JsonBuffer(string json) _buffer = new StringBuilder(json); } - /// - /// Initializes a new instance of the class. - /// + /// Initializes a new instance of the class. /// The reader. - public JsonBuffer(TextReader reader) + /// + /// + public JsonBuffer(TextReader reader, int readChunkSize, int minResetBufferSize) { if (reader == null) { @@ -55,6 +57,10 @@ public JsonBuffer(TextReader reader) } _buffer = new StringBuilder(256); // start out with a reasonable initial capacity _reader = reader; + + // TODO BD validation + _readChunkSize = readChunkSize; + _minDiscardBufferSize = minResetBufferSize; } // public properties @@ -146,8 +152,7 @@ public int Read() public void ResetBuffer() { // only trim the buffer if enough space will be reclaimed to make it worthwhile - var minimumTrimCount = 256; // TODO: make configurable? - if (_position >= minimumTrimCount) + if (_position >= _minDiscardBufferSize) { _buffer.Remove(0, _position); _position = 0; @@ -189,9 +194,8 @@ private void ReadMoreIfAtEndOfBuffer() { if (_reader != null) { - var blockSize = 1024; // TODO: make configurable? - var block = new char[blockSize]; - var actualCount = _reader.ReadBlock(block, 0, blockSize); + var block = new char[_readChunkSize]; + var actualCount = _reader.ReadBlock(block, 0, _readChunkSize); if (actualCount > 0) { diff --git a/src/MongoDB.Bson/IO/JsonReader.cs b/src/MongoDB.Bson/IO/JsonReader.cs index e640585a256..a0c67c95412 100644 --- a/src/MongoDB.Bson/IO/JsonReader.cs +++ b/src/MongoDB.Bson/IO/JsonReader.cs @@ -72,6 +72,8 @@ public class JsonReader : BsonReader private BsonValue _currentValue; private JsonToken _pushedToken; + private readonly List _bookmarks = new List(); + // constructors /// /// Initializes a new instance of the JsonReader class. @@ -107,7 +109,7 @@ public JsonReader(TextReader textReader) /// The TextReader. /// The reader settings. public JsonReader(TextReader textReader, JsonReaderSettings settings) - : this(new JsonBuffer(textReader), settings) + : this(new JsonBuffer(textReader, settings.ReadChunkSize, settings.MinResetBufferSize), settings) { } @@ -135,7 +137,10 @@ public override void Close() /// A bookmark. public override BsonReaderBookmark GetBookmark() { - return new JsonReaderBookmark(State, CurrentBsonType, CurrentName, _context, _currentToken, _currentValue, _pushedToken, _buffer.Position); + var bookmark = new JsonReaderBookmark(State, CurrentBsonType, CurrentName, _context, _currentToken, _currentValue, _pushedToken, _buffer.Position); + _bookmarks.Add(bookmark); + + return bookmark; } /// @@ -399,6 +404,12 @@ public override BsonType ReadBsonType() State = BsonReaderState.Value; break; } + + if (_jsonReaderSettings.AutoBufferReset && _bookmarks.Count == 0) + { + _buffer.ResetBuffer(); + } + return CurrentBsonType; } @@ -749,6 +760,7 @@ public override void ReadUndefined() public override void ReturnToBookmark(BsonReaderBookmark bookmark) { if (Disposed) { ThrowObjectDisposedException(); } + var jsonReaderBookmark = (JsonReaderBookmark)bookmark; State = jsonReaderBookmark.State; CurrentBsonType = jsonReaderBookmark.CurrentBsonType; @@ -758,6 +770,9 @@ public override void ReturnToBookmark(BsonReaderBookmark bookmark) _currentValue = jsonReaderBookmark.CurrentValue; _pushedToken = jsonReaderBookmark.PushedToken; _buffer.Position = jsonReaderBookmark.Position; + + // TODO BD throw if not found? + _bookmarks.Remove(jsonReaderBookmark); } /// diff --git a/src/MongoDB.Bson/IO/JsonReaderSettings.cs b/src/MongoDB.Bson/IO/JsonReaderSettings.cs index 2c00ea2b54a..4d98d2bfd61 100644 --- a/src/MongoDB.Bson/IO/JsonReaderSettings.cs +++ b/src/MongoDB.Bson/IO/JsonReaderSettings.cs @@ -28,6 +28,21 @@ public class JsonReaderSettings : BsonReaderSettings // private static fields private static JsonReaderSettings __defaults = null; // delay creation to pick up the latest default values + /// + /// TODO BD + /// + public bool AutoBufferReset { get; set; } = true; + + /// + /// TODO BD + /// + public int ReadChunkSize { get; set; } = 2048; + + /// + /// TODO BD + /// + public int MinResetBufferSize { get; set; } = 512; + // constructors /// /// Initializes a new instance of the JsonReaderSettings class.