adding
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
namespace LCU.API.Internal.Document.PerformanceTest.API;
|
||||
|
||||
public static class ApiFactory
|
||||
{
|
||||
public static IDocumentApi Api => Environment.Type switch
|
||||
{
|
||||
EnvironmentType.Local => new DirectInMemoryDocumentApi(),
|
||||
EnvironmentType.Azure => new DirectInMemoryDocumentApi(),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
using LCU.API.Internal.Document.Configurations;
|
||||
using LCU.API.Internal.Document.Controllers;
|
||||
using LCU.API.Internal.Document.PerformanceTest.DB;
|
||||
using LCU.API.Internal.DocumentLib.Configurations;
|
||||
using LCU.API.Internal.DocumentLib.DataAccess;
|
||||
using LCU.Library.Internal.DocumentModels.Requests.Search;
|
||||
using LCU.Library.Internal.DocumentModels.Responses;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace LCU.API.Internal.Document.PerformanceTest.API;
|
||||
|
||||
public class DirectInMemoryDocumentApi : IDocumentApi
|
||||
{
|
||||
private IServiceProvider? _services;
|
||||
|
||||
public Task SpinUp(DatabaseConfiguration databaseConfiguration)
|
||||
{
|
||||
if (_services is not null) return Task.CompletedTask;
|
||||
|
||||
var services = new ServiceCollection();
|
||||
ServiceRegistrations.AddDocumentServices(services);
|
||||
ServiceRegistrations.AddDocumentDataAccesses(services);
|
||||
ServiceRegistrations.AddDocumentRepositories(services);
|
||||
services.AddTransient<DocumentController>();
|
||||
services.TryAddSingleton(databaseConfiguration);
|
||||
services.AddSingleton<IBlobStorageClient, NullBlobStorageClient>();
|
||||
services.AddSingleton<ApiConfiguration>();
|
||||
services.AddSingleton<NotificationApiConfiguration>();
|
||||
_services = services.BuildServiceProvider();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task<IList<DocumentInformationResponse>> GetDocumentInformationByFilter(DocumentInformationFilter filter)
|
||||
{
|
||||
var controller = _services?.GetRequiredService<DocumentController>() ?? throw new InvalidOperationException();
|
||||
var response = await controller.PostDocumentInformationByFilter(new DocumentInformationFilteredSearch{ Filter = filter });
|
||||
|
||||
return (response as OkObjectResult)?.Value as IList<DocumentInformationResponse> ?? throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public Task TearDown()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
using LCU.API.Internal.DocumentLib.Configurations;
|
||||
using LCU.Library.Internal.DocumentModels.Requests.Search;
|
||||
using LCU.Library.Internal.DocumentModels.Responses;
|
||||
|
||||
namespace LCU.API.Internal.Document.PerformanceTest.API;
|
||||
|
||||
public interface IDocumentApi
|
||||
{
|
||||
Task SpinUp(DatabaseConfiguration databaseConfiguration);
|
||||
Task<IList<DocumentInformationResponse>> GetDocumentInformationByFilter(DocumentInformationFilter filter);
|
||||
Task TearDown();
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
using Azure;
|
||||
using Azure.Core;
|
||||
using Azure.Identity;
|
||||
using Azure.ResourceManager;
|
||||
using Azure.ResourceManager.CosmosDB;
|
||||
using Azure.ResourceManager.CosmosDB.Models;
|
||||
using Azure.ResourceManager.Resources;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LCU.API.Internal.Document.PerformanceTest.DB;
|
||||
|
||||
public class AzureCosmosDb : IDatabase
|
||||
{
|
||||
private readonly string _performanceTestingResourceName = "Perf_MongoDb";
|
||||
|
||||
public async Task<IMongoClient> SpinUp()
|
||||
{
|
||||
Console.WriteLine("Currently in Azure Spin Up.");
|
||||
//todo test this - cd: I'm not connected to the landmark subscription in the portal, only AD
|
||||
var azureClient = new ArmClient(new DefaultAzureCredential());
|
||||
var subscription = await azureClient.GetDefaultSubscriptionAsync();
|
||||
var resourceGroup = (
|
||||
await subscription
|
||||
.GetResourceGroups()
|
||||
.CreateOrUpdateAsync
|
||||
(
|
||||
WaitUntil.Completed,
|
||||
_performanceTestingResourceName,
|
||||
new ResourceGroupData(AzureLocation.CentralUS)
|
||||
)
|
||||
)
|
||||
.Value;
|
||||
|
||||
var cosmosAccount = (
|
||||
await resourceGroup
|
||||
.GetCosmosDBAccounts()
|
||||
.CreateOrUpdateAsync
|
||||
(
|
||||
WaitUntil.Completed,
|
||||
_performanceTestingResourceName.ToLower().Replace("_",""),
|
||||
new CosmosDBAccountCreateOrUpdateContent
|
||||
(
|
||||
AzureLocation.CentralUS,
|
||||
new CosmosDBAccountLocation[] {
|
||||
new CosmosDBAccountLocation {
|
||||
LocationName = AzureLocation.CentralUS,
|
||||
FailoverPriority = 0,
|
||||
IsZoneRedundant = false
|
||||
},
|
||||
new CosmosDBAccountLocation {
|
||||
LocationName = AzureLocation.EastUS2,
|
||||
FailoverPriority = 1,
|
||||
IsZoneRedundant = false
|
||||
}
|
||||
}
|
||||
)
|
||||
{ Kind = "MongoDB"}
|
||||
)
|
||||
)
|
||||
.Value;
|
||||
|
||||
var mongoDb = cosmosAccount.GetMongoDBDatabases();
|
||||
|
||||
await mongoDb
|
||||
.CreateOrUpdateAsync
|
||||
(
|
||||
WaitUntil.Completed,
|
||||
_performanceTestingResourceName,
|
||||
new MongoDBDatabaseCreateOrUpdateContent
|
||||
(
|
||||
AzureLocation.CentralUS,
|
||||
new MongoDBDatabaseResourceInfo(_performanceTestingResourceName)
|
||||
)
|
||||
);
|
||||
|
||||
//todo test to ensure that there's only one connection string or that it can be determined which is the one we need for mongo
|
||||
var allConnections = cosmosAccount
|
||||
.GetConnectionStrings()
|
||||
.AsPages()
|
||||
.ToArray()
|
||||
.SelectMany(p => p.Values)
|
||||
.ToArray();
|
||||
if (allConnections.Length == 0) throw new Exception("No Connection Strings Found.");
|
||||
_connectionString = cosmosAccount.GetConnectionStrings().AsPages().ToArray()[0].Values[0].ConnectionString;
|
||||
|
||||
return new MongoClient(ConnectionString);
|
||||
}
|
||||
|
||||
public async Task TearDown()
|
||||
{
|
||||
var azureClient = new ArmClient(new DefaultAzureCredential());
|
||||
var subscription = await azureClient.GetDefaultSubscriptionAsync();
|
||||
var resourceGroup = (await subscription.GetResourceGroupAsync(_performanceTestingResourceName)).Value;
|
||||
await resourceGroup.DeleteAsync(WaitUntil.Completed);
|
||||
}
|
||||
|
||||
public string ConnectionString => _connectionString ?? throw new InvalidOperationException("spin up the database first");
|
||||
private string? _connectionString;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
namespace LCU.API.Internal.Document.PerformanceTest.DB;
|
||||
|
||||
public static class DatabaseFactory
|
||||
{
|
||||
public static IDatabase Database => Environment.Type switch
|
||||
{
|
||||
EnvironmentType.Local => new LocalMongoDatabase(),
|
||||
EnvironmentType.Azure => new AzureCosmosDb(),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LCU.API.Internal.Document.PerformanceTest.DB;
|
||||
|
||||
public interface IDatabase
|
||||
{
|
||||
Task<IMongoClient> SpinUp();
|
||||
Task TearDown();
|
||||
string ConnectionString { get; }
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
using Mongo2Go;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LCU.API.Internal.Document.PerformanceTest.DB;
|
||||
|
||||
public class LocalMongoDatabase : IDatabase
|
||||
{
|
||||
private MongoDbRunner? _mongoDb;
|
||||
|
||||
public Task<IMongoClient> SpinUp()
|
||||
{
|
||||
_mongoDb ??= MongoDbRunner.Start();
|
||||
|
||||
return Task.FromResult<IMongoClient>(new MongoClient(ConnectionString));
|
||||
}
|
||||
|
||||
public Task TearDown()
|
||||
{
|
||||
_mongoDb?.Dispose();
|
||||
_mongoDb = null;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public string ConnectionString => _mongoDb?.ConnectionString ?? throw new InvalidOperationException("spin up the database first");
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
using Azure.Storage.Blobs;
|
||||
using LCU.API.Internal.DocumentLib.DataAccess;
|
||||
|
||||
namespace LCU.API.Internal.Document.PerformanceTest.DB;
|
||||
|
||||
public class NullBlobStorageClient : IBlobStorageClient
|
||||
{
|
||||
public BlobContainerClient GetClient() => null!;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace LCU.API.Internal.Document.PerformanceTest;
|
||||
|
||||
public enum EnvironmentType
|
||||
{
|
||||
Local,
|
||||
Azure
|
||||
}
|
||||
|
||||
public static class Environment
|
||||
{
|
||||
public static EnvironmentType Type { get; set; } = EnvironmentType.Local;
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using LCU.API.Internal.Document.PerformanceTest.API;
|
||||
using LCU.API.Internal.Document.PerformanceTest.DB;
|
||||
using LCU.API.Internal.DocumentLib.Configurations;
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
using LCU.Library.Internal.DocumentModels.Requests.Search;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LCU.API.Internal.Document.PerformanceTest;
|
||||
|
||||
[RPlotExporter]
|
||||
public class GetDocumentInformationByFilterLoadTest
|
||||
{
|
||||
static GetDocumentInformationByFilterLoadTest()
|
||||
{
|
||||
Environment.Type = EnvironmentType.Local;
|
||||
}
|
||||
|
||||
//[Params(1, 10, 100, 1000, 10000, 100000, 250000, 500000, 750000, 1000000, 2000000)]
|
||||
[Params(1, 10, 100, 1000, 10000, 100000, 250000, 500000, 750000, 1000000)]
|
||||
public int DocumentCount { get; set; }
|
||||
|
||||
private DocumentInformation _document = null!;
|
||||
|
||||
private readonly DatabaseConfiguration _config;
|
||||
private readonly IDatabase _database = DatabaseFactory.Database;
|
||||
private readonly IDocumentApi _api = ApiFactory.Api;
|
||||
|
||||
private IMongoClient _client = null!;
|
||||
|
||||
public GetDocumentInformationByFilterLoadTest()
|
||||
{
|
||||
_config = new DatabaseConfiguration
|
||||
{
|
||||
DatabaseName = $"{DocumentCount}Documents",
|
||||
DocumentContainerName = "Documents",
|
||||
AuditContainerName = "Audits"
|
||||
};
|
||||
}
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
_client = _database.SpinUp().Result;
|
||||
_config.ConnectionString = _database.ConnectionString;
|
||||
|
||||
var db = _client.GetDatabase(_config.DatabaseName);
|
||||
db.CreateCollection(_config.DocumentContainerName);
|
||||
db.CreateCollection(_config.AuditContainerName);
|
||||
var documentCollection = db.GetCollection<DocumentInformation>(_config.DocumentContainerName);
|
||||
|
||||
Task.WaitAll
|
||||
(
|
||||
_api.SpinUp(_config),
|
||||
documentCollection.InsertManyAsync(Enumerable.Repeat(() => DocumentFactory(), DocumentCount).Select(f => f()))
|
||||
);
|
||||
}
|
||||
|
||||
[IterationSetup]
|
||||
public void Setup()
|
||||
{
|
||||
_document = DocumentFactory();
|
||||
|
||||
_client.GetDatabase(_config.DatabaseName)
|
||||
.GetCollection<DocumentInformation>(_config.DocumentContainerName)
|
||||
.InsertOne(_document);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void GetDocumentInformationByFilterRun()
|
||||
{
|
||||
var oneThirdAttributes = _document.Attributes.Count / 3;
|
||||
var filter = new DocumentInformationFilter
|
||||
{
|
||||
AttributesContains = _document.Attributes.ToArray()[..oneThirdAttributes].ToDictionary(p => p.Key, p => p.Value),
|
||||
AttributesContainsAny = _document.Attributes.ToArray()[oneThirdAttributes..^oneThirdAttributes].ToDictionary(p => p.Key, p => p.Value),
|
||||
AttributesEquals = _document.Attributes.ToArray()[^oneThirdAttributes..].ToDictionary(p => p.Key, p => p.Value),
|
||||
DataSource = _document.DataSource,
|
||||
Name = _document.Name,
|
||||
Type = _document.Type,
|
||||
Source = _document.Source,
|
||||
ScanStatus = _document.ScanStatus,
|
||||
};
|
||||
|
||||
_api.GetDocumentInformationByFilter(filter).Wait();
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
public void GlobalCleanup()
|
||||
{
|
||||
_client.DropDatabase(_config.DatabaseName);
|
||||
|
||||
var dbDestruction = _database.TearDown();
|
||||
var apiDestruction = _api.TearDown();
|
||||
|
||||
Task.WaitAll(dbDestruction, apiDestruction);
|
||||
}
|
||||
|
||||
private static readonly Random Random = new Random(DateTime.Now.Millisecond);
|
||||
private static DocumentInformation DocumentFactory() => new()
|
||||
{
|
||||
Name = Guid.NewGuid().ToString(),
|
||||
Type = Random.Next().ToString(),
|
||||
Source = Random.Next().ToString(),
|
||||
DataSource = Random.Next().ToString(),
|
||||
FileSize = Random.Next(),
|
||||
ScanStatus = Random.Next() % 2 == 0,
|
||||
UploadDate = DateTime.Now.AddDays(-Random.Next(1, 10)),
|
||||
LastModifiedDate = DateTime.Now.AddDays(-Random.Next(1, 10)),
|
||||
CreatedDate = DateTime.Now.AddDays(-Random.Next(1, 10)),
|
||||
Attributes = Enumerable
|
||||
.Repeat
|
||||
(
|
||||
() => new KeyValuePair<string, string>(Guid.NewGuid().ToString(), Random.Next().ToString()),
|
||||
Random.Next(10, 100)
|
||||
)
|
||||
.Select(f => f())
|
||||
.ToDictionary(p => p.Key, p => p.Value)
|
||||
};
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
using System.Configuration;
|
||||
using Azure.Identity;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using LCU.API.Internal.Document.PerformanceTest.API;
|
||||
using LCU.API.Internal.DocumentLib.Configurations;
|
||||
using LCU.API.Internal.DocumentLib.Containers;
|
||||
using LCU.Library.Internal.DocumentModels.Requests.Search;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LCU.API.Internal.Document.PerformanceTest;
|
||||
|
||||
public enum Indexing
|
||||
{
|
||||
Default,
|
||||
FieldSpecific,
|
||||
Wildcard
|
||||
}
|
||||
|
||||
//todo it would be great to get the RU cost output
|
||||
[RPlotExporter]
|
||||
[ShortRunJob]
|
||||
public class IndexingStrategyPerformanceTest
|
||||
{
|
||||
[Params(Indexing.Default, Indexing.FieldSpecific, Indexing.Wildcard)]
|
||||
public Indexing Strategy { get; set; }
|
||||
|
||||
private readonly IDocumentApi _api = ApiFactory.Api;
|
||||
private readonly DatabaseConfiguration _config = new();
|
||||
|
||||
public IndexingStrategyPerformanceTest()
|
||||
{
|
||||
var configBuilder = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddJsonFile("appsettings.Development.json");
|
||||
var baseConfig = configBuilder.Build();
|
||||
|
||||
var clientSecretCredentials = new ClientSecretCredential
|
||||
(
|
||||
baseConfig["TenantId"],
|
||||
baseConfig["ClientId"],
|
||||
baseConfig["ClientSecret"]
|
||||
);
|
||||
var vaultLocation = new Uri($"https://{baseConfig["AzureKeyVaultUrl"]}.vault.azure.net/");
|
||||
configBuilder
|
||||
.AddAzureKeyVault(vaultLocation, clientSecretCredentials)
|
||||
.Build()
|
||||
.Bind("MongoDatabase", _config);
|
||||
}
|
||||
|
||||
[GlobalSetup]
|
||||
public void GlobalSetup()
|
||||
{
|
||||
switch (Strategy)
|
||||
{
|
||||
case Indexing.Default:
|
||||
break;
|
||||
case Indexing.FieldSpecific:
|
||||
new MongoClient(_config.ConnectionString)
|
||||
.GetDatabase(_config.DatabaseName)
|
||||
.GetCollection<DocumentInformation>(_config.DocumentContainerName)
|
||||
.Indexes
|
||||
.CreateOne
|
||||
(
|
||||
new CreateIndexModel<DocumentInformation>
|
||||
(
|
||||
Builders<DocumentInformation>.IndexKeys.Ascending(d => d.Name),
|
||||
new CreateIndexOptions { Name = nameof(DocumentInformation.Name) }
|
||||
)
|
||||
);
|
||||
break;
|
||||
case Indexing.Wildcard:
|
||||
new MongoClient(_config.ConnectionString)
|
||||
.GetDatabase(_config.DatabaseName)
|
||||
.GetCollection<DocumentInformation>(_config.DocumentContainerName)
|
||||
.Indexes
|
||||
.CreateOne
|
||||
(
|
||||
new CreateIndexModel<DocumentInformation>
|
||||
(
|
||||
Builders<DocumentInformation>.IndexKeys.Wildcard(),
|
||||
new CreateIndexOptions { Name = "wildcard" }
|
||||
)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
_api.SpinUp(_config).Wait();
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
//todo report the RU cost in the benchmark
|
||||
public async Task DocumentSearch_ByName()
|
||||
{
|
||||
var filter = new DocumentInformationFilter
|
||||
{
|
||||
Name = "5498-SA"
|
||||
};
|
||||
|
||||
await _api.GetDocumentInformationByFilter(filter);
|
||||
}
|
||||
|
||||
[GlobalCleanup]
|
||||
public void GlobalCleanup()
|
||||
{
|
||||
switch (Strategy)
|
||||
{
|
||||
case Indexing.Default:
|
||||
break;
|
||||
case Indexing.FieldSpecific:
|
||||
new MongoClient(_config.ConnectionString)
|
||||
.GetDatabase(_config.DatabaseName)
|
||||
.GetCollection<DocumentInformation>(_config.DocumentContainerName)
|
||||
.Indexes
|
||||
.DropOne(nameof(DocumentInformation.Name));
|
||||
break;
|
||||
case Indexing.Wildcard:
|
||||
new MongoClient(_config.ConnectionString)
|
||||
.GetDatabase(_config.DatabaseName)
|
||||
.GetCollection<DocumentInformation>(_config.DocumentContainerName)
|
||||
.Indexes
|
||||
.DropOne("wildcard");
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.ResourceManager" Version="1.3.1" />
|
||||
<PackageReference Include="Azure.ResourceManager.CosmosDB" Version="1.0.0" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
|
||||
<PackageReference Include="Mongo2Go" Version="3.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\LCU.API.Internal.Document\appsettings.json" Link="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LCU.API.Internal.DocumentLib\LCU.API.Internal.DocumentLib.csproj" />
|
||||
<ProjectReference Include="..\LCU.API.Internal.Document\LCU.API.Internal.Document.csproj" />
|
||||
<ProjectReference Include="..\LCU.Library.Internal.DocumentModels\LCU.Library.Internal.DocumentModels.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,5 @@
|
||||
using BenchmarkDotNet.Running;
|
||||
using LCU.API.Internal.Document.PerformanceTest;
|
||||
|
||||
//BenchmarkRunner.Run<GetDocumentInformationByFilterLoadTest>();
|
||||
BenchmarkRunner.Run<IndexingStrategyPerformanceTest>();
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
@@ -0,0 +1,122 @@
|
||||
# Running Benchmarks
|
||||
|
||||
`dotnet run -c Release`
|
||||
|
||||
## past results
|
||||
|
||||
### 2022.09.09 - local mongodb - "old" regex matching
|
||||
note: default mongodb indexing is not the same as CosmosDB Mongo default indexing
|
||||
``` ini
|
||||
|
||||
BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19042.1826/20H2/October2020Update)
|
||||
11th Gen Intel Core i5-1145G7 2.60GHz, 1 CPU, 8 logical and 4 physical cores
|
||||
.NET SDK=6.0.400
|
||||
[Host] : .NET 6.0.8 (6.0.822.36306), X64 RyuJIT AVX2
|
||||
Job-HPFGMU : .NET 6.0.8 (6.0.822.36306), X64 RyuJIT AVX2
|
||||
|
||||
InvocationCount=1 UnrollFactor=1
|
||||
|
||||
```
|
||||
| Method | DocumentCount | Mean | Error | StdDev |
|
||||
|---------------------------------- |-------------- |--------------:|--------------:|--------------:|
|
||||
| **GetDocumentInformationByFilterRun** | **1** | **3.756 ms** | **0.6389 ms** | **1.874 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **10** | **3.868 ms** | **0.6174 ms** | **1.820 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **100** | **8.027 ms** | **1.0094 ms** | **2.976 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **1000** | **41.938 ms** | **7.9785 ms** | **23.525 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **10000** | **337.205 ms** | **51.8841 ms** | **152.167 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **100000** | **3,429.605 ms** | **632.3863 ms** | **1,864.605 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **250000** | **7,896.811 ms** | **1,431.8274 ms** | **4,221.775 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **500000** | **16,629.300 ms** | **2,749.5569 ms** | **8,107.131 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **750000** | **23,883.445 ms** | **4,083.3474 ms** | **11,911.316 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **1000000** | **32,725.371 ms** | **5,751.8744 ms** | **16,778.487 ms** |
|
||||

|
||||
|
||||
### 2022.09.12 - local mongodb - "new" regex matching
|
||||
``` ini
|
||||
|
||||
BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19042.1826/20H2/October2020Update)
|
||||
11th Gen Intel Core i5-1145G7 2.60GHz, 1 CPU, 8 logical and 4 physical cores
|
||||
.NET SDK=6.0.400
|
||||
[Host] : .NET 6.0.8 (6.0.822.36306), X64 RyuJIT AVX2
|
||||
Job-ZGOEWK : .NET 6.0.8 (6.0.822.36306), X64 RyuJIT AVX2
|
||||
|
||||
InvocationCount=1 UnrollFactor=1
|
||||
|
||||
```
|
||||
| Method | DocumentCount | Mean | Error | StdDev | Median |
|
||||
|---------------------------------- |-------------- |--------------:|--------------:|--------------:|--------------:|
|
||||
| **GetDocumentInformationByFilterRun** | **1** | **3.924 ms** | **0.6009 ms** | **1.724 ms** | **3.724 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **10** | **3.675 ms** | **0.6997 ms** | **2.063 ms** | **3.096 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **100** | **5.679 ms** | **0.8358 ms** | **2.464 ms** | **5.332 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **1000** | **35.936 ms** | **5.6629 ms** | **16.697 ms** | **37.860 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **10000** | **305.437 ms** | **53.4368 ms** | **157.560 ms** | **291.339 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **100000** | **2,946.267 ms** | **483.7081 ms** | **1,418.632 ms** | **2,793.991 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **250000** | **8,456.390 ms** | **1,315.9931 ms** | **3,796.941 ms** | **8,575.654 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **500000** | **15,775.558 ms** | **2,830.8954 ms** | **8,167.781 ms** | **15,527.663 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **750000** | **24,948.355 ms** | **3,861.0450 ms** | **11,323.777 ms** | **25,630.684 ms** |
|
||||
| **GetDocumentInformationByFilterRun** | **1000000** | **30,470.661 ms** | **5,342.0572 ms** | **15,583.032 ms** | **29,073.994 ms** |
|
||||

|
||||
|
||||
### 2022.09.28 - indexing strategies
|
||||
``` ini
|
||||
|
||||
BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19042.1826/20H2/October2020Update)
|
||||
11th Gen Intel Core i5-1145G7 2.60GHz, 1 CPU, 8 logical and 4 physical cores
|
||||
.NET SDK=6.0.400
|
||||
[Host] : .NET 6.0.8 (6.0.822.36306), X64 RyuJIT AVX2
|
||||
ShortRun : .NET 6.0.8 (6.0.822.36306), X64 RyuJIT AVX2
|
||||
|
||||
Job=ShortRun IterationCount=3 LaunchCount=1
|
||||
WarmupCount=3
|
||||
|
||||
```
|
||||
| Method | Strategy | Mean | Error | StdDev |
|
||||
|---------------------- |-------------- |----------:|---------:|---------:|
|
||||
| **DocumentSearch_ByName** | **Default** | **171.51 ms** | **68.40 ms** | **3.749 ms** |
|
||||
| **DocumentSearch_ByName** | **FieldSpecific** | **91.36 ms** | **29.19 ms** | **1.600 ms** |
|
||||
| **DocumentSearch_ByName** | **Wildcard** | **94.74 ms** | **78.58 ms** | **4.307 ms** |
|
||||

|
||||
|
||||
## required tools
|
||||
- dotnet 6+
|
||||
-- `choco install dotnet`
|
||||
-- probably installed with visual studio
|
||||
- R
|
||||
-- `choco install r.project` then add "C:\Program Files\R\R-4.2.1\bin" to your path, assuming you used the default install directory and the version is 4.2.1
|
||||
--- better to manually add to the path because setx will only give you 1024 characters. Your path is likely already longer than that and will get truncated.
|
||||
-- this is for outputting visual graphs, not just text tables into standard out
|
||||
|
||||
## output
|
||||
- written to the console
|
||||
- `.\BenchmarkDotNet.Artifacts` relative to where ever you ran the code from
|
||||
|
||||
### graphs
|
||||
The plots should be produced automatically and you'll find them in the results folder.
|
||||
|
||||
If not you can manually generate them:
|
||||
- `cd .\BenchmarkDotNet.Artifacts\results`
|
||||
- `rscript BuildPlots.R`
|
||||
|
||||
## benchmarkdotnet docs
|
||||
https://benchmarkdotnet.org/
|
||||
|
||||
## gotchas
|
||||
|
||||
### Debugging
|
||||
This will be more difficult than you might be accustomed to. By default benchmark dotnet takes control of a lot of parts of the runtime and even rebuilds some parts of the assembly to ensure isolation and consistent optimzation. See their docs for enabling debugging.
|
||||
|
||||
It's possible to run or attach to a release optimized assembly. Some of the things you might expect to be there won't be availabe to the debugger; you're missing debug symbols and the IL has been optimized.
|
||||
|
||||
There's always good old console output and file logging.
|
||||
|
||||
You might also want to try setting up the problematic scenario in a unit test and then debug *that* instead of debugging the benchmark itself.
|
||||
|
||||
### Singletons
|
||||
Benchmarkdotnet ends up invoking msbuild in order to build separate assemblies (for controlling optimization and isolation). This means that, e.g. `Environment.Type = EnvironmentType.Azure;` in program.cs will not affect the benchmarks when they are run; Environment.Type will be recreated every benchmark because benchmarks are running in a different assembly than the `BenchmarkRunner.Run<T>();` statement which caused the benchmark to run.
|
||||
|
||||
One option to deal with this is setting the option inside the benchmark class e.g. in a static constructor (ensuring the value is set before anything else). There are almost surely other options, perhaps a way to pass arguments (other than `[Params()]`) to the benchmark class.
|
||||
|
||||
### Azure Rate Limiting
|
||||
Despite having an Azure environment with code to spin it up and tear it down trying to run a benchmark against a real Azure CosmosDB will likely run you into rate limiting issues. Specifically inserting enough documents to produce a notable database load in a short amount of time. As of 2022.09.13 the rate limit is 1000 records per 5 minutes... You can see where this might produce a problem trying to produce a database on the order of hundreds of thousands of records.
|
||||
|
||||
See https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/request-limits-and-throttling#network-throttling for current information.
|
||||
Reference in New Issue
Block a user