-
Couldn't load subscription status.
- Fork 1.3k
CSHARP-5348: Avoid allocations for Bson*Context #1791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |||||
| */ | ||||||
|
|
||||||
| using System; | ||||||
| using System.Collections.Generic; | ||||||
| using System.Globalization; | ||||||
| using System.IO; | ||||||
|
|
||||||
|
|
@@ -30,6 +31,7 @@ public class BsonBinaryReader : BsonReader | |||||
| #pragma warning restore CA2213 // Disposable never disposed | ||||||
| private readonly BsonStream _bsonStream; | ||||||
| private BsonBinaryReaderContext _context; | ||||||
| private readonly Stack<BsonBinaryReaderContext> _contextStack = new(4); | ||||||
|
|
||||||
| // constructors | ||||||
| /// <summary> | ||||||
|
|
@@ -61,7 +63,7 @@ public BsonBinaryReader(Stream stream, BsonBinaryReaderSettings settings) | |||||
| _baseStream = stream; | ||||||
| _bsonStream = (stream as BsonStream) ?? new BsonStreamAdapter(stream); | ||||||
|
|
||||||
| _context = new BsonBinaryReaderContext(null, ContextType.TopLevel, 0, 0); | ||||||
| _context = new BsonBinaryReaderContext(ContextType.TopLevel, 0, 0); | ||||||
| } | ||||||
|
|
||||||
| // public properties | ||||||
|
|
@@ -109,10 +111,8 @@ public override void Close() | |||||
| /// Gets a bookmark to the reader's current position and state. | ||||||
| /// </summary> | ||||||
| /// <returns>A bookmark.</returns> | ||||||
| public override BsonReaderBookmark GetBookmark() | ||||||
| { | ||||||
| return new BsonBinaryReaderBookmark(State, CurrentBsonType, CurrentName, _context, _bsonStream.Position); | ||||||
| } | ||||||
| public override BsonReaderBookmark GetBookmark() => | ||||||
| new BsonBinaryReaderBookmark(State, CurrentBsonType, CurrentName, _context, _contextStack, _bsonStream.Position); | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Determines whether this reader is at end of file. | ||||||
|
|
@@ -201,12 +201,11 @@ public override BsonType ReadBsonType() | |||||
|
|
||||||
| if (_context.ContextType == ContextType.Array) | ||||||
| { | ||||||
| _context.CurrentArrayIndex++; | ||||||
| _context.ArrayIndex++; | ||||||
| } | ||||||
|
|
||||||
| try | ||||||
| { | ||||||
|
|
||||||
| CurrentBsonType = _bsonStream.ReadBsonType(); | ||||||
| } | ||||||
| catch (FormatException ex) | ||||||
|
|
@@ -342,7 +341,8 @@ public override void ReadEndArray() | |||||
| ThrowInvalidState("ReadEndArray", BsonReaderState.EndOfArray); | ||||||
| } | ||||||
|
|
||||||
| _context = _context.PopContext(_bsonStream.Position); | ||||||
| PopContext(); | ||||||
|
|
||||||
| switch (_context.ContextType) | ||||||
| { | ||||||
| case ContextType.Array: State = BsonReaderState.Type; break; | ||||||
|
|
@@ -371,10 +371,10 @@ public override void ReadEndDocument() | |||||
| ThrowInvalidState("ReadEndDocument", BsonReaderState.EndOfDocument); | ||||||
| } | ||||||
|
|
||||||
| _context = _context.PopContext(_bsonStream.Position); | ||||||
| PopContext(); | ||||||
| if (_context.ContextType == ContextType.JavaScriptWithScope) | ||||||
| { | ||||||
| _context = _context.PopContext(_bsonStream.Position); // JavaScriptWithScope | ||||||
| PopContext(); // JavaScriptWithScope | ||||||
| } | ||||||
| switch (_context.ContextType) | ||||||
| { | ||||||
|
|
@@ -432,7 +432,9 @@ public override string ReadJavaScriptWithScope() | |||||
|
|
||||||
| var startPosition = _bsonStream.Position; // position of size field | ||||||
| var size = ReadSize(); | ||||||
| _context = new BsonBinaryReaderContext(_context, ContextType.JavaScriptWithScope, startPosition, size); | ||||||
|
|
||||||
| PushContext(new(ContextType.JavaScriptWithScope, startPosition, size)); | ||||||
|
|
||||||
| var code = _bsonStream.ReadString(Settings.Encoding); | ||||||
|
|
||||||
| State = BsonReaderState.ScopeDocument; | ||||||
|
|
@@ -486,7 +488,7 @@ public override string ReadName(INameDecoder nameDecoder) | |||||
|
|
||||||
| if (_context.ContextType == ContextType.Document) | ||||||
| { | ||||||
| _context.CurrentElementName = CurrentName; | ||||||
| _context.ElementName = CurrentName; | ||||||
| } | ||||||
|
|
||||||
| return CurrentName; | ||||||
|
|
@@ -553,7 +555,7 @@ public override IByteBuffer ReadRawBsonDocument() | |||||
|
|
||||||
| if (_context.ContextType == ContextType.JavaScriptWithScope) | ||||||
| { | ||||||
| _context = _context.PopContext(_bsonStream.Position); // JavaScriptWithScope | ||||||
| PopContext(); // JavaScriptWithScope | ||||||
| } | ||||||
| switch (_context.ContextType) | ||||||
| { | ||||||
|
|
@@ -590,7 +592,9 @@ public override void ReadStartArray() | |||||
|
|
||||||
| var startPosition = _bsonStream.Position; // position of size field | ||||||
| var size = ReadSize(); | ||||||
| _context = new BsonBinaryReaderContext(_context, ContextType.Array, startPosition, size); | ||||||
|
|
||||||
| PushContext(new(ContextType.Array, startPosition, size)); | ||||||
|
|
||||||
| State = BsonReaderState.Type; | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -605,7 +609,9 @@ public override void ReadStartDocument() | |||||
| var contextType = (State == BsonReaderState.ScopeDocument) ? ContextType.ScopeDocument : ContextType.Document; | ||||||
| var startPosition = _bsonStream.Position; // position of size field | ||||||
| var size = ReadSize(); | ||||||
| _context = new BsonBinaryReaderContext(_context, contextType, startPosition, size); | ||||||
|
|
||||||
| PushContext(new(contextType, startPosition, size)); | ||||||
|
|
||||||
| State = BsonReaderState.Type; | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -662,10 +668,11 @@ public override void ReadUndefined() | |||||
| public override void ReturnToBookmark(BsonReaderBookmark bookmark) | ||||||
| { | ||||||
| var binaryReaderBookmark = (BsonBinaryReaderBookmark)bookmark; | ||||||
|
|
||||||
| State = binaryReaderBookmark.State; | ||||||
| CurrentBsonType = binaryReaderBookmark.CurrentBsonType; | ||||||
| CurrentName = binaryReaderBookmark.CurrentName; | ||||||
| _context = binaryReaderBookmark.CloneContext(); | ||||||
| _context = binaryReaderBookmark.RestoreContext(_contextStack); | ||||||
| _bsonStream.Position = binaryReaderBookmark.Position; | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -686,7 +693,7 @@ public override void SkipName() | |||||
|
|
||||||
| if (_context.ContextType == ContextType.Document) | ||||||
| { | ||||||
| _context.CurrentElementName = CurrentName; | ||||||
| _context.ElementName = CurrentName; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -745,7 +752,7 @@ protected override void Dispose(bool disposing) | |||||
| { | ||||||
| Close(); | ||||||
| } | ||||||
| catch { } // ignore exceptions | ||||||
| catch { /* ignore exceptions */ } | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make Rider happier. |
||||||
| } | ||||||
| base.Dispose(disposing); | ||||||
| } | ||||||
|
|
@@ -767,35 +774,41 @@ private string GenerateDottedElementName() | |||||
| } | ||||||
| else if (_context.ContextType == ContextType.Array) | ||||||
| { | ||||||
| elementName = _context.CurrentArrayIndex.ToString(NumberFormatInfo.InvariantInfo); | ||||||
| elementName = _context.ArrayIndex.ToString(NumberFormatInfo.InvariantInfo); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| elementName = "?"; | ||||||
| } | ||||||
|
|
||||||
| return GenerateDottedElementName(_context.ParentContext, elementName); | ||||||
| return GenerateDottedElementName(_contextStack.ToArray(), 0, elementName); | ||||||
| } | ||||||
|
|
||||||
| private string GenerateDottedElementName(BsonBinaryReaderContext context, string elementName) | ||||||
| private string GenerateDottedElementName(BsonBinaryReaderContext[] contexts, int currentContextIndex, string elementName) | ||||||
| { | ||||||
| if (currentContextIndex >= contexts.Length) | ||||||
| return elementName; | ||||||
|
|
||||||
| var context = contexts[currentContextIndex]; | ||||||
| var nextIndex = currentContextIndex + 1; | ||||||
|
|
||||||
| if (context.ContextType == ContextType.Document) | ||||||
| { | ||||||
| return GenerateDottedElementName(context.ParentContext, (context.CurrentElementName ?? "?") + "." + elementName); | ||||||
| } | ||||||
| else if (context.ContextType == ContextType.Array) | ||||||
| { | ||||||
| var indexElementName = context.CurrentArrayIndex.ToString(NumberFormatInfo.InvariantInfo); | ||||||
| return GenerateDottedElementName(context.ParentContext, indexElementName + "." + elementName); | ||||||
| return GenerateDottedElementName(contexts, nextIndex, (context.ElementName ?? "?") + "." + elementName); | ||||||
|
||||||
| return GenerateDottedElementName(contexts, nextIndex, (context.ElementName ?? "?") + "." + elementName); | |
| return GenerateDottedElementName(contexts, nextIndex, (context.ElementName ?? "?") + "." + elementName); |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra space after comma in method calls.
| return GenerateDottedElementName(contexts, nextIndex, indexElementName + "." + elementName); | |
| return GenerateDottedElementName(contexts, nextIndex, indexElementName + "." + elementName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's encapsulate all side effects of popping the context in the
PopContextmethod (see below).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, done.