Skip to content

Commit 9ea6e66

Browse files
authored
CSHARP-4719: Benchmark performance of in-use Encryption (#1216)
1 parent 12dd384 commit 9ea6e66

File tree

6 files changed

+147
-12
lines changed

6 files changed

+147
-12
lines changed

benchmarks/MongoDB.Driver.Benchmarks/BenchmarkRunner.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,30 @@ public class BenchmarkRunner
2424
{
2525
public static void Main(string[] args)
2626
{
27+
var executingDriverBenchmarks = false;
2728
var exportingToEvergreen = false;
28-
var evergreenOutputFile = "evergreen-results.json";
29+
var evergreenOutputFile = "evergreen-results.json"; // default output file name
2930

3031
var parser = new OptionSet
3132
{
3233
{ "evergreen", v => exportingToEvergreen = v != null },
34+
{ "driverBenchmarks", v => executingDriverBenchmarks = v != null },
3335
{ "o|output-file=", v => evergreenOutputFile = v }
3436
};
3537

3638
// the parser will try to parse the options defined above and will return any extra options
3739
var benchmarkSwitcherArgs = parser.Parse(args).ToArray();
3840

39-
var config = DefaultConfig.Instance
40-
.WithOption(ConfigOptions.JoinSummary, true)
41-
.AddExporter(new LocalExporter())
42-
.HideColumns("BenchmarkDataSetSize");
41+
var config = DefaultConfig.Instance;
42+
43+
// use a modified config if running driver benchmarks
44+
if (executingDriverBenchmarks)
45+
{
46+
config = config
47+
.WithOption(ConfigOptions.JoinSummary, true)
48+
.AddExporter(new LocalExporter())
49+
.HideColumns("BenchmarkDataSetSize");
50+
}
4351

4452
if (exportingToEvergreen)
4553
{
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/* 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+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.Threading;
19+
using BenchmarkDotNet.Attributes;
20+
using MongoDB.Bson;
21+
using MongoDB.Bson.TestHelpers;
22+
using MongoDB.Driver;
23+
using MongoDB.Driver.Core.Clusters;
24+
using MongoDB.Driver.Encryption;
25+
using MongoDB.Driver.TestHelpers;
26+
using MongoDB.Libmongocrypt;
27+
28+
namespace MongoDB.Benchmarks
29+
{
30+
public class LibmongocryptBindingBenchmark
31+
{
32+
private const int RepeatCount = 10;
33+
private const string LocalMasterKey = "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk";
34+
35+
private byte[] _encryptedValuesDocumentBytes;
36+
private DisposableMongoClient _disposableKeyVaultClient;
37+
private AutoEncryptionLibMongoCryptController _libMongoCryptController;
38+
private CryptClient _cryptClient;
39+
40+
[Params(1, 2, 8, 64)]
41+
public int ThreadsCount { get; set; }
42+
43+
[GlobalSetup]
44+
public void Setup()
45+
{
46+
var localMasterKey = Convert.FromBase64String(LocalMasterKey);
47+
48+
var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
49+
var localKey = new Dictionary<string, object> { { "key", localMasterKey } };
50+
kmsProviders.Add("local", localKey);
51+
52+
var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
53+
var autoEncryptionOptions = new AutoEncryptionOptions(
54+
keyVaultNamespace: keyVaultNamespace,
55+
kmsProviders: kmsProviders,
56+
bypassAutoEncryption: true);
57+
58+
var clientSettings = MongoClientSettings.FromConnectionString("mongodb://localhost");
59+
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
60+
61+
_disposableKeyVaultClient = new DisposableMongoClient(new MongoClient(clientSettings), null);
62+
63+
var keyVaultDatabase = _disposableKeyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);
64+
keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);
65+
_disposableKeyVaultClient.DropDatabase("crypt-test");
66+
67+
var clientEncryptionSettings = new ClientEncryptionOptions(
68+
_disposableKeyVaultClient,
69+
keyVaultNamespace,
70+
kmsProviders);
71+
72+
var encryptedValuesDocument = new BsonDocument();
73+
using (var clientEncryption = new ClientEncryption(clientEncryptionSettings))
74+
{
75+
var dataKeyId = clientEncryption.CreateDataKey(
76+
"local",
77+
new DataKeyOptions(),
78+
CancellationToken.None);
79+
80+
var encryptOptions = new EncryptOptions(
81+
EncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.ToString(),
82+
keyId: dataKeyId);
83+
84+
for (int i = 0; i < 1500; i++)
85+
{
86+
var toEncryptString = $"value {(i + 1):D4}";
87+
var encryptedString =
88+
clientEncryption.Encrypt(toEncryptString, encryptOptions, CancellationToken.None);
89+
encryptedValuesDocument.Add(new BsonElement($"key{(i + 1):D4}", encryptedString));
90+
}
91+
}
92+
_encryptedValuesDocumentBytes = encryptedValuesDocument.ToBson();
93+
94+
// Create libmongocrypt binding that will be used for decryption
95+
_cryptClient = CryptClientCreator.CreateCryptClient(autoEncryptionOptions.ToCryptClientSettings());
96+
_libMongoCryptController = AutoEncryptionLibMongoCryptController.Create(_disposableKeyVaultClient, _cryptClient, autoEncryptionOptions);
97+
}
98+
99+
[Benchmark]
100+
public void BulkDecryptionUsingBinding()
101+
{
102+
ThreadingUtilities.ExecuteOnNewThreads(ThreadsCount, _ =>
103+
{
104+
for (int i = 0; i < RepeatCount; i++)
105+
{
106+
_libMongoCryptController.DecryptFields(_encryptedValuesDocumentBytes, CancellationToken.None);
107+
}
108+
}, 20000);
109+
}
110+
111+
[GlobalCleanup]
112+
public void Cleanup()
113+
{
114+
_cryptClient.Dispose();
115+
_disposableKeyVaultClient.Dispose();
116+
}
117+
}
118+
}

benchmarks/MongoDB.Driver.Benchmarks/README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22

33
This suite implements the benchmarks described in this [spec](https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst).
44

5-
## Running the Benchmarks
5+
## Running the Driver Benchmarks
66

77
- Run `/scripts/download-data.sh` to download the data used for the benchmarks. Make sure to run the download script and the benchmarks from
88
the benchmark root (directory containing this README).
9-
- Run `dotnet run -c Release` which will start the benchmark runner and give you the option to select which benchmarks to run. Follow
10-
the prompts on the console. Make sure to have a mongod instance running on localhost (or you can specify a custom connection string
9+
- Run `dotnet run -c Release -- --driverBenchmarks` which will start the benchmark runner and give you the option to select which benchmarks to run. Follow
10+
the prompts on the console (the `--driverBenchmarks` options runs the benchmarks using a special config for driver benchmarks). Make sure to have a mongod instance running on localhost (or you can specify a custom connection string
1111
by setting the `MONGODB_URI` environment variable). You can set the environment variable as an exported console variable or using
1212
the `--envVars KEY:VALUE` option with the command for running the benchmarks.
13-
(e.g `dotnet run -c Release -- --envVars MONGODB_URI:"ConnectionString"`)
13+
(e.g `dotnet run -c Release -- --driverBenchmarks --envVars MONGODB_URI:"ConnectionString"`)
1414

1515
You can also select the benchmarks to run directly on the command for running the benchmarks as such
16-
`dotnet run -c Release -- --fitler "*BenchmarkClassName*"`. The benchmarks are also grouped into categories namely: BSONBench, WriteBench
16+
`dotnet run -c Release -- --driverBenchmarks --fitler "*BenchmarkClassName*"`. The benchmarks are also grouped into categories namely: BSONBench, WriteBench
1717
ReadBench, ParallelBench, SingleBench, MultiBench and DriverBench. So if you wanted to only run the WriteBench benchmarks, you can do so
18-
as follows: `dotnet run -c Release -- --anyCategories "WriteBench"`.
18+
as follows: `dotnet run -c Release -- --driverBenchmarks --anyCategories "WriteBench"`.
1919

2020
Note: You can provide multiple categories but the `--anyCategories` option will select benchmarks that belong to any of the categories.
2121
You can use the `--allCategories` option to select benchmarks that belong to all the provided categories.
@@ -39,3 +39,9 @@ More information on BenchmarkDotNet can be found [here](https://benchmarkdotnet.
3939
There is a python script in the `/scripts` folder called `compare-results` that can be used to compare the results of different
4040
benchmark runs. The script expects json files in the format of the exported file for evergreen, so you will to have run the benchmarks
4141
with the `--evergreen` option to generate the evergreen results json file in order to compare different benchmark runs.
42+
43+
## Running other Benchmarks
44+
45+
Other benchmarks defined in this project that are not part of the driver benchmark spec
46+
can also be run using the benchmark runner. You can do the same things as described in the Running the
47+
Driver Benchmarks section to run your benchmarks. Just omit the `--driverBenchmarks` option.

benchmarks/MongoDB.Driver.Benchmarks/SingleDoc/RunCommandBenchmark.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
namespace MongoDB.Benchmarks.SingleDoc
2222
{
2323
[IterationTime(3000)]
24+
[BenchmarkCategory("RunBench")]
2425
public class RunCommandBenchmark
2526
{
2627
private DisposableMongoClient _client;

evergreen/run-perf-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ set -o errexit # Exit the script with error if any of the commands fail
99
# Download the data to be used in the performance tests
1010
./scripts/download-data.sh .
1111

12-
dotnet run -c Release -- --evergreen --filter '*' --a ./Benchmark.Artifacts
12+
dotnet run -c Release -- --driverBenchmarks --evergreen --anyCategories "DriverBench" "BsonBench" "RunBench" --a ./Benchmark.Artifacts

src/MongoDB.Driver/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@
3131
[assembly: InternalsVisibleTo("MongoDB.Driver.Tests")]
3232
[assembly: InternalsVisibleTo("MongoDB.Driver.TestHelpers")]
3333
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
34+
[assembly: InternalsVisibleTo("MongoDB.Driver.Benchmarks")]
35+

0 commit comments

Comments
 (0)