Skip to content

Commit 5de47d4

Browse files
authored
CSHARP-5807: Add benchmarks with strong-typed POCOs (#1839)
1 parent 833f164 commit 5de47d4

27 files changed

+1522
-965
lines changed

benchmarks/MongoDB.Driver.Benchmarks/BenchmarkHelper.cs

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -21,74 +21,73 @@
2121
using MongoDB.Bson;
2222
using MongoDB.Driver;
2323

24-
namespace MongoDB.Benchmarks
24+
namespace MongoDB.Benchmarks;
25+
26+
public static class BenchmarkHelper
2527
{
26-
public static class BenchmarkHelper
27-
{
28-
public const string DataFolderPath = "../../../../../../../data/";
28+
public const string DataFolderPath = "../../../../../../../data/";
2929

30-
public static void AddFilesToQueue(ConcurrentQueue<(string, int)> filesQueue, string directoryPath, string fileNamePrefix, int fileCount)
30+
public static void AddFilesToQueue(ConcurrentQueue<(string, int)> filesQueue, string directoryPath, string fileNamePrefix, int fileCount)
31+
{
32+
var addingLDJSONfiles = fileNamePrefix == "ldjson";
33+
for (int i = 0; i < fileCount; i++)
3134
{
32-
var addingLDJSONfiles = fileNamePrefix == "ldjson";
33-
for (int i = 0; i < fileCount; i++)
34-
{
35-
var fileName = addingLDJSONfiles ? $"{fileNamePrefix}{i:D3}.txt" : $"{fileNamePrefix}{i:D2}.txt";
36-
filesQueue.Enqueue(($"{directoryPath}/{fileName}", i)); // enqueue complete filepath and filenumber
37-
}
35+
var fileName = addingLDJSONfiles ? $"{fileNamePrefix}{i:D3}.txt" : $"{fileNamePrefix}{i:D2}.txt";
36+
filesQueue.Enqueue(($"{directoryPath}/{fileName}", i)); // enqueue complete filepath and filenumber
3837
}
38+
}
3939

40-
public static double CalculateCompositeScore(IEnumerable<BenchmarkResult> benchmarkResults, string benchmarkCategory)
41-
{
42-
var identifiedBenchmarksScores = benchmarkResults
43-
.Where(benchmark => benchmark.Categories.Contains(benchmarkCategory))
44-
.Select(benchmark => benchmark.Score).ToArray();
45-
46-
if (identifiedBenchmarksScores.Any())
47-
{
48-
return identifiedBenchmarksScores.Average();
49-
}
50-
51-
return 0;
52-
}
40+
public static double CalculateCompositeScore(IEnumerable<BenchmarkResult> benchmarkResults, string benchmarkCategory)
41+
{
42+
var identifiedBenchmarksScores = benchmarkResults
43+
.Where(benchmark => benchmark.Categories.Contains(benchmarkCategory))
44+
.Select(benchmark => benchmark.Score).ToArray();
5345

54-
public static void CreateEmptyDirectory(string path)
46+
if (identifiedBenchmarksScores.Any())
5547
{
56-
if (Directory.Exists(path))
57-
{
58-
Directory.Delete(path, true);
59-
}
60-
Directory.CreateDirectory(path);
48+
return identifiedBenchmarksScores.Average();
6149
}
6250

63-
public static BsonDocument ReadExtendedJson(string resourcePath)
64-
{
65-
var extendedJson = File.ReadAllText(DataFolderPath + resourcePath);
66-
return BsonDocument.Parse(extendedJson);
67-
}
51+
return 0;
52+
}
6853

69-
public static byte[] ReadExtendedJsonToBytes(string resourcePath)
54+
public static void CreateEmptyDirectory(string path)
55+
{
56+
if (Directory.Exists(path))
7057
{
71-
var extendedJson = File.ReadAllText(DataFolderPath + resourcePath);
72-
var document = BsonDocument.Parse(extendedJson);
73-
return document.ToBson();
58+
Directory.Delete(path, true);
7459
}
60+
Directory.CreateDirectory(path);
61+
}
7562

76-
public static class MongoConfiguration
77-
{
78-
public const string PerfTestDatabaseName = "perftest";
79-
public const string PerfTestCollectionName = "corpus";
63+
public static BsonDocument ReadExtendedJson(string resourcePath)
64+
{
65+
var extendedJson = File.ReadAllText(DataFolderPath + resourcePath);
66+
return BsonDocument.Parse(extendedJson);
67+
}
8068

81-
public static IMongoClient CreateClient()
82-
{
83-
var mongoUri = Environment.GetEnvironmentVariable("MONGODB_URI");
84-
var settings = mongoUri != null ? MongoClientSettings.FromConnectionString(mongoUri) : new();
85-
settings.ClusterSource = DisposingClusterSource.Instance;
69+
public static byte[] ReadExtendedJsonToBytes(string resourcePath)
70+
{
71+
var extendedJson = File.ReadAllText(DataFolderPath + resourcePath);
72+
var document = BsonDocument.Parse(extendedJson);
73+
return document.ToBson();
74+
}
75+
76+
public static class MongoConfiguration
77+
{
78+
public const string PerfTestDatabaseName = "perftest";
79+
public const string PerfTestCollectionName = "corpus";
80+
81+
public static IMongoClient CreateClient()
82+
{
83+
var mongoUri = Environment.GetEnvironmentVariable("MONGODB_URI");
84+
var settings = mongoUri != null ? MongoClientSettings.FromConnectionString(mongoUri) : new();
85+
settings.ClusterSource = DisposingClusterSource.Instance;
8686

87-
var client = new MongoClient(settings);
88-
client.DropDatabase(PerfTestDatabaseName);
87+
var client = new MongoClient(settings);
88+
client.DropDatabase(PerfTestDatabaseName);
8989

90-
return client;
91-
}
90+
return client;
9291
}
9392
}
94-
}
93+
}

benchmarks/MongoDB.Driver.Benchmarks/BenchmarkResult.cs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,44 @@
1717
using BenchmarkDotNet.Reports;
1818
using MongoDB.Benchmarks.Bson;
1919

20-
namespace MongoDB.Benchmarks
20+
namespace MongoDB.Benchmarks;
21+
22+
public sealed class BenchmarkResult
2123
{
22-
public sealed class BenchmarkResult
24+
public HashSet<string> Categories { get; }
25+
public string Name { get; }
26+
public double Score { get; }
27+
28+
public BenchmarkResult(BenchmarkReport benchmarkReport)
2329
{
24-
public HashSet<string> Categories { get; }
25-
public string Name { get; }
26-
public double Score { get; }
30+
var benchmarkCaseDescriptor = benchmarkReport.BenchmarkCase.Descriptor;
31+
var methodName = benchmarkCaseDescriptor.WorkloadMethod.Name;
32+
Categories = new HashSet<string>(benchmarkCaseDescriptor.Categories);
33+
34+
int dataSetSize;
35+
if (Categories.Contains(DriverBenchmarkCategory.BsonBench))
36+
{
37+
var bsonBenchmarkData = (BsonBenchmarkData)benchmarkReport.BenchmarkCase.Parameters["BenchmarkData"];
38+
Name = bsonBenchmarkData.DataSetName + benchmarkCaseDescriptor.Type.Name;
39+
40+
dataSetSize = bsonBenchmarkData.DataSetSize;
41+
}
42+
else
43+
{
44+
Name = Categories.Contains(DriverBenchmarkCategory.BulkWriteBench)
45+
? methodName
46+
: benchmarkCaseDescriptor.Type.Name;
2747

28-
public BenchmarkResult(BenchmarkReport benchmarkReport)
48+
dataSetSize = (int)benchmarkReport.BenchmarkCase.Parameters["BenchmarkDataSetSize"];
49+
}
50+
51+
if (methodName.EndsWith("Poco") || methodName.EndsWith("PocoBenchmark"))
2952
{
30-
Categories = new HashSet<string>(benchmarkReport.BenchmarkCase.Descriptor.Categories);
31-
32-
int dataSetSize;
33-
if (Categories.Contains(DriverBenchmarkCategory.BsonBench))
34-
{
35-
var bsonBenchmarkData = (BsonBenchmarkData)benchmarkReport.BenchmarkCase.Parameters["BenchmarkData"];
36-
Name = bsonBenchmarkData.DataSetName + benchmarkReport.BenchmarkCase.Descriptor.Type.Name;
37-
dataSetSize = bsonBenchmarkData.DataSetSize;
38-
}
39-
else
40-
{
41-
Name = Categories.Contains(DriverBenchmarkCategory.BulkWriteBench)
42-
? benchmarkReport.BenchmarkCase.Descriptor.WorkloadMethod.Name
43-
: benchmarkReport.BenchmarkCase.Descriptor.Type.Name;
44-
45-
dataSetSize = (int)benchmarkReport.BenchmarkCase.Parameters["BenchmarkDataSetSize"];
46-
}
47-
48-
// change the median from nanoseconds to seconds for calculating the score.
49-
// since dataSetSize is in bytes, divide the score to convert to MB/s
50-
Score = (dataSetSize / (benchmarkReport.ResultStatistics.Median / 1_000_000_000D)) / 1_000_000D;
53+
Name = Name.Replace("Benchmark", "PocoBenchmark");
5154
}
55+
56+
// change the median from nanoseconds to seconds for calculating the score.
57+
// since dataSetSize is in bytes, divide the score to convert to MB/s
58+
Score = (dataSetSize / (benchmarkReport.ResultStatistics.Median / 1_000_000_000D)) / 1_000_000D;
5259
}
5360
}

benchmarks/MongoDB.Driver.Benchmarks/BenchmarkRunner.cs

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,47 +19,46 @@
1919
using BenchmarkDotNet.Running;
2020
using MongoDB.Benchmarks.Exporters;
2121

22-
namespace MongoDB.Benchmarks
22+
namespace MongoDB.Benchmarks;
23+
24+
public class BenchmarkRunner
2325
{
24-
public class BenchmarkRunner
26+
public static int Main(string[] args)
2527
{
26-
public static int Main(string[] args)
27-
{
28-
var rootCommand = new RootCommand("CSharp Driver benchmarks runner");
29-
rootCommand.TreatUnmatchedTokensAsErrors = false;
30-
var evergreenOption = new Option<bool>("--evergreen", () => false);
31-
rootCommand.AddOption(evergreenOption);
32-
var driverBenchmarksOption = new Option<bool>("--driverBenchmarks", () => false);
33-
rootCommand.AddOption(driverBenchmarksOption);
34-
var evergreenOutputFileOption = new Option<string>(["--o", "--output-file"], () => "evergreen-results.json");
35-
rootCommand.AddOption(evergreenOutputFileOption);
28+
var rootCommand = new RootCommand("CSharp Driver benchmarks runner");
29+
rootCommand.TreatUnmatchedTokensAsErrors = false;
30+
var evergreenOption = new Option<bool>("--evergreen", () => false);
31+
rootCommand.AddOption(evergreenOption);
32+
var driverBenchmarksOption = new Option<bool>("--driverBenchmarks", () => false);
33+
rootCommand.AddOption(driverBenchmarksOption);
34+
var evergreenOutputFileOption = new Option<string>(["--o", "--output-file"], () => "evergreen-results.json");
35+
rootCommand.AddOption(evergreenOutputFileOption);
3636

37-
rootCommand.SetHandler(invocationContext =>
38-
{
39-
var evergreenValue = invocationContext.ParseResult.GetValueForOption(evergreenOption);
40-
var driverBenchmarksValue = invocationContext.ParseResult.GetValueForOption(driverBenchmarksOption);
41-
var evergreenOutputFileValue = invocationContext.ParseResult.GetValueForOption(evergreenOutputFileOption);
37+
rootCommand.SetHandler(invocationContext =>
38+
{
39+
var evergreenValue = invocationContext.ParseResult.GetValueForOption(evergreenOption);
40+
var driverBenchmarksValue = invocationContext.ParseResult.GetValueForOption(driverBenchmarksOption);
41+
var evergreenOutputFileValue = invocationContext.ParseResult.GetValueForOption(evergreenOutputFileOption);
4242

43-
var config = DefaultConfig.Instance;
43+
var config = DefaultConfig.Instance;
4444

45-
// use a modified config if running driver benchmarks
46-
if (driverBenchmarksValue)
47-
{
48-
config = config
49-
.WithOption(ConfigOptions.JoinSummary, true)
50-
.AddExporter(new LocalExporter())
51-
.HideColumns("BenchmarkDataSetSize");
52-
}
45+
// use a modified config if running driver benchmarks
46+
if (driverBenchmarksValue)
47+
{
48+
config = config
49+
.WithOption(ConfigOptions.JoinSummary, true)
50+
.AddExporter(new LocalExporter())
51+
.HideColumns("BenchmarkDataSetSize");
52+
}
5353

54-
if (evergreenValue)
55-
{
56-
config = config.AddExporter(new EvergreenExporter(evergreenOutputFileValue));
57-
}
54+
if (evergreenValue)
55+
{
56+
config = config.AddExporter(new EvergreenExporter(evergreenOutputFileValue));
57+
}
5858

59-
BenchmarkSwitcher.FromAssembly(typeof(BenchmarkRunner).Assembly).Run(invocationContext.ParseResult.UnmatchedTokens.ToArray(), config);
60-
});
59+
BenchmarkSwitcher.FromAssembly(typeof(BenchmarkRunner).Assembly).Run(invocationContext.ParseResult.UnmatchedTokens.ToArray(), config);
60+
});
6161

62-
return rootCommand.Invoke(args);
63-
}
62+
return rootCommand.Invoke(args);
6463
}
6564
}
Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
/* Copyright 2010-present MongoDB Inc.
2-
*
3-
* Licensed under the Apache License, Version 2.0 (the "License");
4-
* you may not use this file except in compliance with the License.
5-
* You may obtain a copy of the License at
6-
*
7-
* http://www.apache.org/licenses/LICENSE-2.0
8-
*
9-
* Unless required by applicable law or agreed to in writing, software
10-
* distributed under the License is distributed on an "AS IS" BASIS,
11-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
* See the License for the specific language governing permissions and
13-
* limitations under the License.
14-
*/
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
1515

16-
namespace MongoDB.Benchmarks.Bson
16+
using System;
17+
18+
namespace MongoDB.Benchmarks.Bson;
19+
20+
public readonly record struct BsonBenchmarkData(string FilePath, string DataSetName, int DataSetSize, Type PocoType)
1721
{
18-
public readonly record struct BsonBenchmarkData(string FilePath, string DataSetName, int DataSetSize)
19-
{
20-
public override string ToString() => $"{DataSetName}";
21-
}
22+
public override string ToString() => $"{DataSetName}";
2223
}

0 commit comments

Comments
 (0)