Skip to content

Instantly share code, notes, and snippets.

@Herve-M
Created August 27, 2019 04:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Herve-M/01558b9903bdc522afc93b89e27ebb1c to your computer and use it in GitHub Desktop.
Save Herve-M/01558b9903bdc522afc93b89e27ebb1c to your computer and use it in GitHub Desktop.
mongo-csharp-driver benchmark
using System;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.IdGenerators;
namespace MongoDBBench.Benchmark.MongoDBCsharpDTO
{
public sealed class BasicClass
{
public BasicClass()
{
}
public BasicClass(int test)
{
var rnd = new Random();
rnd.NextBytes(BytesProp);
BoolProp = Convert.ToBoolean(rnd.Next(0, 1));
IntProp = test;
EnumTest = (EumTest) rnd.Next(0, 3);
}
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId Id { get; set; }
public string StringProp { get; set; } = @"https://duckduckgo.com/?q=";
public int IntProp { get; set; }
public bool BoolProp { get; set; }
public DateTime DateTimeProp { get; set; } = DateTime.UtcNow;
public TimeSpan TimeSpanProp { get; set; } = TimeSpan.FromMinutes(1245684);
public byte[] BytesProp { get; set; } = new byte[20];
[BsonRepresentation(BsonType.String)]
public EumTest EnumTest { get; set; }
}
public enum EumTest
{
Search,
With,
Index,
Test123
}
}
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDBBench.Benchmark.MongoDBCsharpDTO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MongoDBBench.Benchmark
{
[Config(typeof(Config))]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[CategoriesColumn, RankColumn]
public class MongoDBCsharpBench
{
private const string MongoDbDatabase = "mongodb://localhost:27017";
private readonly IMongoClient _mongoClientBson = new MongoClient($"{MongoDbDatabase}/?appname=bsonClient");
private readonly IMongoClient _mongoClientBasic = new MongoClient($"{MongoDbDatabase}/?appname=basicClient");
private readonly IMongoClient _mongoClientBasic2 = new MongoClient($"{MongoDbDatabase}/?appname=basicClient2");
private readonly IMongoClient _mongoClientBasicWithPoolSettings = new MongoClient($"{MongoDbDatabase}/?appname=basicPooledClient&minPoolSize=5&maxPoolSize=100");
private IMongoCollection<BsonDocument> _bsonCollection;
private IMongoCollection<BasicClass> _basicCollection;
private IMongoCollection<BasicClass> _basicCollection2;
private IMongoCollection<BasicClass> _basicPooledCollection;
private readonly Dictionary<IMongoClient, IMongoCollection<BasicClass>> _mongoClients = new Dictionary<IMongoClient, IMongoCollection<BasicClass>>(4);
private readonly FilterDefinition<BasicClass> _filter = Builders<BasicClass>.Filter.Regex(x => x.EnumTest, EumTest.Search.ToString());
private readonly FindOptions _findOptions = new FindOptions() {BatchSize = 500};
[GlobalSetup]
public void GlobalSetup()
{
_bsonCollection = _mongoClientBson.GetDatabase("benchmarkDB").GetCollection<BsonDocument>("benchmark");
_basicCollection = _mongoClientBasic.GetDatabase("benchmarkDB").GetCollection<BasicClass>("benchmark");
_basicCollection2 = _mongoClientBasic2.GetDatabase("benchmarkDB").GetCollection<BasicClass>("benchmark");
_basicPooledCollection = _mongoClientBasicWithPoolSettings.GetDatabase("benchmarkDB").GetCollection<BasicClass>("benchmark");
for (var i = 0; i < 4; i++)
{
var mongoClient = new MongoClient($"{MongoDbDatabase}/?appname=bench-{i}");
_mongoClients.Add(mongoClient, mongoClient.GetDatabase("benchmarkDB").GetCollection<BasicClass>("benchmark"));
}
if (_basicCollection.CountDocuments(FilterDefinition<BasicClass>.Empty) == 0)
{
var toInsert = Enumerable.Range(0, 100000).Select(x => new BasicClass(x));
_basicCollection.InsertMany(toInsert);
var indexTarget = Builders<BasicClass>.IndexKeys;
var indexModel = new CreateIndexModel<BasicClass>(indexTarget.Ascending(x => x.EnumTest));
_basicCollection.Indexes.CreateOne(indexModel);
}
}
[Benchmark]
public BsonDocument BsonReadOne()
{
return _bsonCollection.Find(FilterDefinition<BsonDocument>.Empty).Limit(1).First();
}
[Benchmark]
public BasicClass BasicClassReadOne()
{
return _basicCollection.Find(FilterDefinition<BasicClass>.Empty).Limit(1).First();
}
[Benchmark]
public IList<BasicClass> ReadMultiShared()
{
var concurentBag = new List<BasicClass>(100000);
Parallel.ForEach(_mongoClients, (pair, state, index) =>
{
var values = pair.Value.Find(_filter)
.Skip(25000 * ((int)index))
.Limit(25000)
.ToList();
lock (concurentBag)
{
concurentBag.AddRange(values);
}
});
return concurentBag;
}
[Benchmark]
public async Task<IList<BasicClass>> ReadMultiSharedAsync()
{
var toReturn = new List<BasicClass>(10000);
var t1 = (await _basicCollection.FindAsync(_filter, new FindOptions<BasicClass, BasicClass>()
{
Limit = 50000,
BatchSize = 250,
Skip = 0
}, CancellationToken.None)).ToListAsync();
var t2 = (await _basicCollection2.FindAsync(_filter, new FindOptions<BasicClass, BasicClass>()
{
Limit = 50000,
BatchSize = 250,
Skip = 50000
}, CancellationToken.None)).ToListAsync();
toReturn.AddRange(await t1);
toReturn.AddRange(await t2);
return toReturn;
}
[Benchmark]
public IList<BasicClass> ReadAllSingle()
{
return _basicCollection.Find(_filter).ToList();
}
[Benchmark]
public IList<BasicClass> ReadAllSingleBatched()
{
return _basicCollection.Find(_filter, _findOptions).ToList();
}
[Benchmark]
public IList<BasicClass> ReadAllPooled()
{
return _basicPooledCollection.Find(_filter).ToList();
}
[Benchmark]
public IList<BasicClass> ReadAllPooledBatched()
{
return _basicPooledCollection.Find(_filter, _findOptions).ToList();
}
[GlobalCleanup]
public void GlobalCleanup()
{
}
}
}
@Herve-M
Copy link
Author

Herve-M commented Aug 27, 2019

// * Summary *

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18362
Intel Core i7-4790 CPU 3.60GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100-preview8-013656
[Host] : .NET Core 2.2.2 (CoreCLR 4.6.27317.07, CoreFX 4.6.27318.02), 64bit RyuJIT
Job-TLDPLT : .NET Core 2.2.2 (CoreCLR 4.6.27317.07, CoreFX 4.6.27318.02), 64bit RyuJIT

Toolchain=.NET Core 2.2

Method Mean Error StdDev Rank Gen 0 Gen 1 Gen 2 Allocated
BsonReadOne 751.1 us 14.93 us 18.34 us 1 4.8828 - - 21.15 KB
BasicClassReadOne 746.7 us 14.54 us 14.93 us 1 3.9063 - - 19.99 KB
ReadMultiShared 470,497.3 us 9,346.60 us 24,622.68 us 2 6000.0000 2000.0000 - 30080.36 KB
ReadMultiSharedAsync 550,487.8 us 5,214.82 us 4,877.95 us 4 7000.0000 2000.0000 - 93.48 KB
ReadAllSingle 456,660.0 us 3,444.46 us 3,053.42 us 2 6000.0000 2000.0000 - 39375.26 KB
ReadAllSingleBatched 518,849.0 us 5,919.15 us 4,942.76 us 3 6000.0000 2000.0000 - 40613.15 KB
ReadAllPooled 467,013.4 us 9,034.06 us 12,060.21 us 2 6000.0000 2000.0000 - 39375.26 KB
ReadAllPooledBatched 514,996.9 us 4,387.71 us 4,104.27 us 3 6000.0000 2000.0000 - 40613.15 KB

Docker: docker run -it --name mongoBenchmark -p 27017:27017 -d mongo:latest mongod

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment