diff --git a/benchmarks/MongoDB.Driver.Benchmarks/README.md b/benchmarks/MongoDB.Driver.Benchmarks/README.md index fa07012c742..005c5bd5be6 100644 --- a/benchmarks/MongoDB.Driver.Benchmarks/README.md +++ b/benchmarks/MongoDB.Driver.Benchmarks/README.md @@ -1,6 +1,6 @@ # C# Driver Benchmark Suite -This suite implements the benchmarks described in this [spec](https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst). +This suite implements the benchmarks described in this [spec](https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.md). ## Running the Driver Benchmarks @@ -13,7 +13,7 @@ This suite implements the benchmarks described in this [spec](https://github.com (e.g `dotnet run -c Release -- --driverBenchmarks --envVars MONGODB_URI:"ConnectionString"`) You can also select the benchmarks to run directly on the command for running the benchmarks as such -`dotnet run -c Release -- --driverBenchmarks --fitler "*BenchmarkClassName*"`. The benchmarks are also grouped into categories namely: BSONBench, WriteBench +`dotnet run -c Release -- --driverBenchmarks --filter "*BenchmarkClassName*"`. The benchmarks are also grouped into categories namely: BSONBench, WriteBench ReadBench, ParallelBench, SingleBench, MultiBench and DriverBench. So if you wanted to only run the WriteBench benchmarks, you can do so as follows: `dotnet run -c Release -- --driverBenchmarks --anyCategories "WriteBench"`. diff --git a/src/MongoDB.Bson/IO/BsonBinaryReader.cs b/src/MongoDB.Bson/IO/BsonBinaryReader.cs index 3bf194cd425..4993bffd764 100644 --- a/src/MongoDB.Bson/IO/BsonBinaryReader.cs +++ b/src/MongoDB.Bson/IO/BsonBinaryReader.cs @@ -432,7 +432,7 @@ public override string ReadJavaScriptWithScope() var startPosition = _bsonStream.Position; // position of size field var size = ReadSize(); - _context = new BsonBinaryReaderContext(_context, ContextType.JavaScriptWithScope, startPosition, size); + _context = _context.PushContext(ContextType.JavaScriptWithScope, startPosition, size); var code = _bsonStream.ReadString(Settings.Encoding); State = BsonReaderState.ScopeDocument; @@ -590,7 +590,7 @@ public override void ReadStartArray() var startPosition = _bsonStream.Position; // position of size field var size = ReadSize(); - _context = new BsonBinaryReaderContext(_context, ContextType.Array, startPosition, size); + _context = _context.PushContext(ContextType.Array, startPosition, size); State = BsonReaderState.Type; } @@ -605,7 +605,7 @@ 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); + _context = _context.PushContext(contextType, startPosition, size); State = BsonReaderState.Type; } diff --git a/src/MongoDB.Bson/IO/BsonBinaryReaderContext.cs b/src/MongoDB.Bson/IO/BsonBinaryReaderContext.cs index c4e18381dda..589362a24de 100644 --- a/src/MongoDB.Bson/IO/BsonBinaryReaderContext.cs +++ b/src/MongoDB.Bson/IO/BsonBinaryReaderContext.cs @@ -21,9 +21,10 @@ internal class BsonBinaryReaderContext { // private fields private readonly BsonBinaryReaderContext _parentContext; - private readonly ContextType _contextType; - private readonly long _startPosition; - private readonly long _size; + private BsonBinaryReaderContext _cachedPushContext; + private ContextType _contextType; + private long _startPosition; + private long _size; private string _currentElementName; private int _currentArrayIndex = -1; @@ -83,5 +84,20 @@ public BsonBinaryReaderContext PopContext(long position) } return _parentContext; } + + internal BsonBinaryReaderContext PushContext(ContextType contextType, long startPosition, long size) + { + if (_cachedPushContext == null) + _cachedPushContext = new BsonBinaryReaderContext(this, contextType, startPosition, size); + else + { + _cachedPushContext._contextType = contextType; + _cachedPushContext._startPosition = startPosition; + _cachedPushContext._size = size; + _cachedPushContext._currentArrayIndex = -1; + _cachedPushContext._currentElementName = null; + } + return _cachedPushContext; + } } } diff --git a/src/MongoDB.Bson/IO/BsonBinaryWriter.cs b/src/MongoDB.Bson/IO/BsonBinaryWriter.cs index 42430ef4eb4..b1535347d79 100644 --- a/src/MongoDB.Bson/IO/BsonBinaryWriter.cs +++ b/src/MongoDB.Bson/IO/BsonBinaryWriter.cs @@ -290,7 +290,7 @@ public override void WriteEndArray() _bsonStream.WriteByte(0); BackpatchSize(); // size of document - _context = _context.ParentContext; + _context = _context.PopContext(); State = GetNextState(); } @@ -313,7 +313,7 @@ public override void WriteEndDocument() _bsonStream.WriteByte(0); BackpatchSize(); // size of document - _context = _context.ParentContext; + _context = _context.PopContext(); if (_context == null) { State = BsonWriterState.Done; @@ -323,7 +323,7 @@ public override void WriteEndDocument() if (_context.ContextType == ContextType.JavaScriptWithScope) { BackpatchSize(); // size of the JavaScript with scope value - _context = _context.ParentContext; + _context = _context.PopContext(); } State = GetNextState(); } @@ -400,7 +400,7 @@ public override void WriteJavaScriptWithScope(string code) _bsonStream.WriteBsonType(BsonType.JavaScriptWithScope); WriteNameHelper(); - _context = new BsonBinaryWriterContext(_context, ContextType.JavaScriptWithScope, _bsonStream.Position); + _context = _context.PushContext(ContextType.JavaScriptWithScope, _bsonStream.Position); _bsonStream.WriteInt32(0); // reserve space for size of JavaScript with scope value _bsonStream.WriteString(code, Settings.Encoding); @@ -564,7 +564,7 @@ public override void WriteStartArray() base.WriteStartArray(); _bsonStream.WriteBsonType(BsonType.Array); WriteNameHelper(); - _context = new BsonBinaryWriterContext(_context, ContextType.Array, _bsonStream.Position); + _context = _context.PushContext(ContextType.Array, _bsonStream.Position); _bsonStream.WriteInt32(0); // reserve space for size State = BsonWriterState.Value; @@ -588,7 +588,10 @@ public override void WriteStartDocument() WriteNameHelper(); } var contextType = (State == BsonWriterState.ScopeDocument) ? ContextType.ScopeDocument : ContextType.Document; - _context = new BsonBinaryWriterContext(_context, contextType, _bsonStream.Position); + if (_context == null) + _context = new BsonBinaryWriterContext(null, contextType, _bsonStream.Position); + else + _context = _context.PushContext(contextType, _bsonStream.Position); _bsonStream.WriteInt32(0); // reserve space for size State = BsonWriterState.Name; diff --git a/src/MongoDB.Bson/IO/BsonBinaryWriterContext.cs b/src/MongoDB.Bson/IO/BsonBinaryWriterContext.cs index fb791ab4fc3..8512e9d56de 100644 --- a/src/MongoDB.Bson/IO/BsonBinaryWriterContext.cs +++ b/src/MongoDB.Bson/IO/BsonBinaryWriterContext.cs @@ -18,7 +18,8 @@ namespace MongoDB.Bson.IO internal class BsonBinaryWriterContext { // private fields - private BsonBinaryWriterContext _parentContext; + private readonly BsonBinaryWriterContext _parentContext; + private BsonBinaryWriterContext _cachedPushContext; private ContextType _contextType; private long _startPosition; private int _index; // used when contextType is Array @@ -55,5 +56,23 @@ internal int Index get { return _index; } set { _index = value; } } + + internal BsonBinaryWriterContext PopContext() + { + return _parentContext; + } + + internal BsonBinaryWriterContext PushContext(ContextType contextType, long startPosition) + { + if (_cachedPushContext == null) + _cachedPushContext = new BsonBinaryWriterContext(this, contextType, startPosition); + else + { + _cachedPushContext._contextType = contextType; + _cachedPushContext._startPosition = startPosition; + _cachedPushContext._index = 0; + } + return _cachedPushContext; + } } } diff --git a/src/MongoDB.Bson/IO/BsonDocumentReader.cs b/src/MongoDB.Bson/IO/BsonDocumentReader.cs index aa4a1e93252..2231bee8be0 100644 --- a/src/MongoDB.Bson/IO/BsonDocumentReader.cs +++ b/src/MongoDB.Bson/IO/BsonDocumentReader.cs @@ -413,7 +413,7 @@ public override void ReadStartArray() VerifyBsonType("ReadStartArray", BsonType.Array); var array = _currentValue.AsBsonArray; - _context = new BsonDocumentReaderContext(_context, ContextType.Array, array); + _context = _context.PushContext(ContextType.Array, array); State = BsonReaderState.Type; } @@ -435,7 +435,7 @@ public override void ReadStartDocument() { document = _currentValue.AsBsonDocument; } - _context = new BsonDocumentReaderContext(_context, ContextType.Document, document); + _context = _context.PushContext(ContextType.Document, document); State = BsonReaderState.Type; } diff --git a/src/MongoDB.Bson/IO/BsonDocumentReaderContext.cs b/src/MongoDB.Bson/IO/BsonDocumentReaderContext.cs index 9208be4ae0f..aa5013eb5ee 100644 --- a/src/MongoDB.Bson/IO/BsonDocumentReaderContext.cs +++ b/src/MongoDB.Bson/IO/BsonDocumentReaderContext.cs @@ -18,20 +18,23 @@ namespace MongoDB.Bson.IO internal class BsonDocumentReaderContext { // private fields - private BsonDocumentReaderContext _parentContext; + private readonly BsonDocumentReaderContext _parentContext; + private BsonDocumentReaderContext _cachedPushContext; private ContextType _contextType; private BsonDocument _document; private BsonArray _array; private int _index; // constructors - internal BsonDocumentReaderContext( + private BsonDocumentReaderContext( BsonDocumentReaderContext parentContext, ContextType contextType, + BsonDocument document, BsonArray array) { _parentContext = parentContext; _contextType = contextType; + _document = document; _array = array; } @@ -124,5 +127,29 @@ public BsonDocumentReaderContext PopContext() { return _parentContext; } + + internal BsonDocumentReaderContext PushContext(ContextType contextType, BsonArray array) + { + return PushContext(contextType, null, array); + } + + internal BsonDocumentReaderContext PushContext(ContextType contextType, BsonDocument document) + { + return PushContext(contextType, document, null); + } + + private BsonDocumentReaderContext PushContext(ContextType contextType, BsonDocument document, BsonArray array) + { + if (_cachedPushContext == null) + _cachedPushContext = new BsonDocumentReaderContext(this, contextType, document, array); + else + { + _cachedPushContext._contextType = contextType; + _cachedPushContext._document = document; + _cachedPushContext._array = array; + _cachedPushContext._index = 0; + } + return _cachedPushContext; + } } } diff --git a/src/MongoDB.Bson/IO/BsonDocumentWriter.cs b/src/MongoDB.Bson/IO/BsonDocumentWriter.cs index 3f77160f1c2..8e5e4ef0b27 100644 --- a/src/MongoDB.Bson/IO/BsonDocumentWriter.cs +++ b/src/MongoDB.Bson/IO/BsonDocumentWriter.cs @@ -195,7 +195,7 @@ public override void WriteEndArray() base.WriteEndArray(); var array = _context.Array; - _context = _context.ParentContext; + _context = _context.PopContext(); WriteValue(array); State = GetNextState(); } @@ -219,15 +219,15 @@ public override void WriteEndDocument() if (_context.ContextType == ContextType.ScopeDocument) { var scope = _context.Document; - _context = _context.ParentContext; + _context = _context.PopContext(); var code = _context.Code; - _context = _context.ParentContext; + _context = _context.PopContext(); WriteValue(new BsonJavaScriptWithScope(code, scope)); } else { var document = _context.Document; - _context = _context.ParentContext; + _context = _context.PopContext(); if (_context != null) { WriteValue(document); @@ -304,7 +304,7 @@ public override void WriteJavaScriptWithScope(string code) ThrowInvalidState("WriteJavaScriptWithScope", BsonWriterState.Value); } - _context = new BsonDocumentWriterContext(_context, ContextType.JavaScriptWithScope, code); + _context = _context.PushContext(ContextType.JavaScriptWithScope, code); State = BsonWriterState.ScopeDocument; } @@ -407,7 +407,7 @@ public override void WriteStartArray() } base.WriteStartArray(); - _context = new BsonDocumentWriterContext(_context, ContextType.Array, new BsonArray()); + _context = _context.PushContext(ContextType.Array, new BsonArray()); State = BsonWriterState.Value; } @@ -430,10 +430,10 @@ public override void WriteStartDocument() _context = new BsonDocumentWriterContext(null, ContextType.Document, _document); break; case BsonWriterState.Value: - _context = new BsonDocumentWriterContext(_context, ContextType.Document, new BsonDocument()); + _context = _context.PushContext(ContextType.Document, new BsonDocument()); break; case BsonWriterState.ScopeDocument: - _context = new BsonDocumentWriterContext(_context, ContextType.ScopeDocument, new BsonDocument()); + _context = _context.PushContext(ContextType.ScopeDocument, new BsonDocument()); break; default: throw new BsonInternalException("Unexpected state."); diff --git a/src/MongoDB.Bson/IO/BsonDocumentWriterContext.cs b/src/MongoDB.Bson/IO/BsonDocumentWriterContext.cs index 4aa1f6ddd82..00f25a8e790 100644 --- a/src/MongoDB.Bson/IO/BsonDocumentWriterContext.cs +++ b/src/MongoDB.Bson/IO/BsonDocumentWriterContext.cs @@ -18,7 +18,8 @@ namespace MongoDB.Bson.IO internal class BsonDocumentWriterContext { // private fields - private BsonDocumentWriterContext _parentContext; + private readonly BsonDocumentWriterContext _parentContext; + private BsonDocumentWriterContext _cachedPushContext; private ContextType _contextType; private BsonDocument _document; private BsonArray _array; @@ -36,23 +37,17 @@ internal BsonDocumentWriterContext( _document = document; } - internal BsonDocumentWriterContext( - BsonDocumentWriterContext parentContext, - ContextType contextType, - BsonArray array) - { - _parentContext = parentContext; - _contextType = contextType; - _array = array; - } - - internal BsonDocumentWriterContext( + private BsonDocumentWriterContext( BsonDocumentWriterContext parentContext, ContextType contextType, + BsonDocument document, + BsonArray array, string code) { _parentContext = parentContext; _contextType = contextType; + _document = document; + _array = array; _code = code; } @@ -87,5 +82,40 @@ internal string Code { get { return _code; } } + + internal BsonDocumentWriterContext PopContext() + { + return _parentContext; + } + + internal BsonDocumentWriterContext PushContext(ContextType contextType, BsonDocument document) + { + return PushContext(contextType, document, null, null); + } + + internal BsonDocumentWriterContext PushContext(ContextType contextType, BsonArray array) + { + return PushContext(contextType, null, array, null); + } + + internal BsonDocumentWriterContext PushContext(ContextType contextType, string code) + { + return PushContext(contextType, null, null, code); + } + + private BsonDocumentWriterContext PushContext(ContextType contextType, BsonDocument document, BsonArray array, string code) + { + if (_cachedPushContext == null) + _cachedPushContext = new BsonDocumentWriterContext(this, contextType, document, array, code); + else + { + _cachedPushContext._contextType = contextType; + _cachedPushContext._document = document; + _cachedPushContext._array = array; + _cachedPushContext._code = code; + _cachedPushContext._name = null; + } + return _cachedPushContext; + } } } diff --git a/src/MongoDB.Bson/IO/JsonReader.cs b/src/MongoDB.Bson/IO/JsonReader.cs index 0d5a483ff60..d26f7846b7c 100644 --- a/src/MongoDB.Bson/IO/JsonReader.cs +++ b/src/MongoDB.Bson/IO/JsonReader.cs @@ -627,7 +627,7 @@ public override string ReadJavaScriptWithScope() { if (Disposed) { ThrowObjectDisposedException(); } VerifyBsonType("ReadJavaScriptWithScope", BsonType.JavaScriptWithScope); - _context = new JsonReaderContext(_context, ContextType.JavaScriptWithScope); + _context = _context.PushContext(ContextType.JavaScriptWithScope); State = BsonReaderState.ScopeDocument; return _currentValue.AsString; } @@ -723,7 +723,7 @@ public override void ReadStartArray() if (Disposed) { ThrowObjectDisposedException(); } VerifyBsonType("ReadStartArray", BsonType.Array); - _context = new JsonReaderContext(_context, ContextType.Array); + _context = _context.PushContext(ContextType.Array); State = BsonReaderState.Type; } @@ -735,7 +735,7 @@ public override void ReadStartDocument() if (Disposed) { ThrowObjectDisposedException(); } VerifyBsonType("ReadStartDocument", BsonType.Document); - _context = new JsonReaderContext(_context, ContextType.Document); + _context = _context.PushContext(ContextType.Document); State = BsonReaderState.Type; } diff --git a/src/MongoDB.Bson/IO/JsonReaderContext.cs b/src/MongoDB.Bson/IO/JsonReaderContext.cs index 94dc554ec39..e93707a4bae 100644 --- a/src/MongoDB.Bson/IO/JsonReaderContext.cs +++ b/src/MongoDB.Bson/IO/JsonReaderContext.cs @@ -18,7 +18,8 @@ namespace MongoDB.Bson.IO internal class JsonReaderContext { // private fields - private JsonReaderContext _parentContext; + private readonly JsonReaderContext _parentContext; + private JsonReaderContext _cachedPushContext; private ContextType _contextType; // constructors @@ -53,5 +54,14 @@ public JsonReaderContext PopContext() { return _parentContext; } + + internal JsonReaderContext PushContext(ContextType contextType) + { + if (_cachedPushContext == null) + _cachedPushContext = new JsonReaderContext(this, contextType); + else + _cachedPushContext._contextType = contextType; + return _cachedPushContext; + } } } diff --git a/src/MongoDB.Bson/IO/JsonWriter.cs b/src/MongoDB.Bson/IO/JsonWriter.cs index 39b884c8618..501cfc4ad01 100644 --- a/src/MongoDB.Bson/IO/JsonWriter.cs +++ b/src/MongoDB.Bson/IO/JsonWriter.cs @@ -312,7 +312,7 @@ public override void WriteEndArray() base.WriteEndArray(); _textWriter.Write("]"); - _context = _context.ParentContext; + _context = _context.PopContext(); State = GetNextState(); } @@ -344,12 +344,12 @@ public override void WriteEndDocument() if (_context.ContextType == ContextType.ScopeDocument) { - _context = _context.ParentContext; + _context = _context.PopContext(); WriteEndDocument(); } else { - _context = _context.ParentContext; + _context = _context.PopContext(); } if (_context == null) @@ -641,7 +641,7 @@ public override void WriteStartArray() WriteNameHelper(Name); _textWriter.Write("["); - _context = new JsonWriterContext(_context, ContextType.Array, Settings.IndentChars); + _context = _context.PushContext(ContextType.Array, Settings.IndentChars); State = BsonWriterState.Value; } @@ -664,7 +664,7 @@ public override void WriteStartDocument() _textWriter.Write("{"); var contextType = (State == BsonWriterState.ScopeDocument) ? ContextType.ScopeDocument : ContextType.Document; - _context = new JsonWriterContext(_context, contextType, Settings.IndentChars); + _context = _context.PushContext(contextType, Settings.IndentChars); State = BsonWriterState.Name; } diff --git a/src/MongoDB.Bson/IO/JsonWriterContext.cs b/src/MongoDB.Bson/IO/JsonWriterContext.cs index c48dc7cef12..cdc8b6c2cee 100644 --- a/src/MongoDB.Bson/IO/JsonWriterContext.cs +++ b/src/MongoDB.Bson/IO/JsonWriterContext.cs @@ -18,7 +18,8 @@ namespace MongoDB.Bson.IO internal class JsonWriterContext { // private fields - private JsonWriterContext _parentContext; + private readonly JsonWriterContext _parentContext; + private JsonWriterContext _cachedPushContext; private ContextType _contextType; private string _indentation; private bool _hasElements = false; @@ -52,5 +53,22 @@ internal bool HasElements get { return _hasElements; } set { _hasElements = value; } } + + internal JsonWriterContext PopContext() + { + return _parentContext; + } + + internal JsonWriterContext PushContext(ContextType contextType, string indentChars) + { + if (_cachedPushContext == null) + _cachedPushContext = new JsonWriterContext(this, contextType, indentChars); + else + { + _cachedPushContext._contextType = contextType; + _cachedPushContext._hasElements = false; + } + return _cachedPushContext; + } } }