Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions benchmark/Prime.Extensions.Benchmarks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

rm -rf BenchmarkDotNet.Artifacts
rm -rf Prime.Extensions.Benchmarks/bin
rm -rf Prime.Extensions.Benchmarks/obj

dotnet run --project Prime.Extensions.Benchmarks/ -c release



149 changes: 149 additions & 0 deletions benchmark/Prime.Extensions.Benchmarks/FindIdsBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using MongoDB.Driver;
using MongoDB.Prime.Extensions;
using Squadron;

namespace Prime.Extensions.Benchmarks
{
[RPlotExporter, CategoriesColumn, RankColumn, MeanColumn, MedianColumn, MemoryDiagnoser]
public class FindIdsBenchmarks
{
private static MongoReplicaSetResource _mongoRsResource;
private static IMongoCollection<Bar> _barCollection;
private static IReadOnlyList<Guid> _200BarsToFind;
private static IReadOnlyList<Guid> _1000BarsToFind;
private static IReadOnlyList<Guid> _5000BarsToFind;
private static IReadOnlyList<Guid> _10000BarsToFind;

[GlobalSetup]
public void GlobalSetup()
{
InitializeOnce().GetAwaiter().GetResult();
}

[Benchmark()]
public Task FindIdsClassic200()
{
return FindClassicAsync(_200BarsToFind);
}

[Benchmark]
public Task FindIdsOptimized200()
{
return FindOptimizedAsync(_200BarsToFind);
}

[Benchmark()]
public Task FindIdsClassic1000()
{
return FindClassicAsync(_1000BarsToFind);
}

[Benchmark]
public Task FindIdsOptimized1000()
{
return FindOptimizedAsync(_1000BarsToFind);
}

[Benchmark()]
public Task FindIdsClassic5000()
{
return FindClassicAsync(_5000BarsToFind);
}

[Benchmark]
public Task FindIdsOptimized5000()
{
return FindOptimizedAsync(_5000BarsToFind);
}

[Benchmark()]
public Task FindIdsClassic10000()
{
return FindClassicAsync(_10000BarsToFind);
}

[Benchmark]
public Task FindIdsOptimized10000()
{
return FindOptimizedAsync(_10000BarsToFind);
}

public async Task FindOptimizedAsync(IReadOnlyList<Guid> barsToFind)
{
IDictionary<Guid, Bar> result = await _barCollection
.FindIdsAsync(barsToFind, bar => bar.Id);

if (result.Count != barsToFind.Count)
throw new Exception("WrongResult");
}

public async Task FindClassicAsync(IReadOnlyList<Guid> barsToFind)
{
FilterDefinition<Bar> filter =
Builders<Bar>.Filter.In(b => b.Id, barsToFind);

List<Bar> bars = await _barCollection
.Find(filter)
.ToListAsync();

var result = bars.ToDictionary(t => t.Id);

if (result.Count != barsToFind.Count)
throw new Exception("WrongResult");
}

private async Task InitializeOnce()
{
if (_10000BarsToFind == null)
{
_mongoRsResource = new MongoReplicaSetResource();

await _mongoRsResource.InitializeAsync();

IMongoDatabase mongoDatabase = _mongoRsResource.CreateDatabase();

_barCollection = mongoDatabase.GetCollection<Bar>();

IReadOnlyList<Bar> alldBars = CreateRandomBars(5_000_000);

await _barCollection.InsertManyAsync(alldBars);

_200BarsToFind = alldBars.Skip(500_000).Take(200).Select(bar => bar.Id).ToList();
_1000BarsToFind = alldBars.Skip(500_000).Take(1000).Select(bar => bar.Id).ToList();
_5000BarsToFind = alldBars.Skip(500_000).Take(5000).Select(bar => bar.Id).ToList();
_10000BarsToFind = alldBars.Skip(500_000).Take(10000).Select(bar => bar.Id).ToList();
}
}

private static IReadOnlyList<Bar> CreateRandomBars(int count)
{
return Enumerable
.Range(0, count)
.Select(number => new Bar(
Guid.NewGuid(),
$"BarName-Unique-{number}",
$"BarValue-{Guid.NewGuid()}"))
.ToList();
}

private class Bar
{
public Bar(Guid id, string name, string value)
{
Id = id;
Name = name;
Value = value;
}

public Guid Id { get; }

public string Name { get; }
public string Value { get; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Squadron.Mongo" Version="0.9.0" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Prime.Extensions\Prime.Extensions.csproj" />
</ItemGroup>

</Project>
15 changes: 15 additions & 0 deletions benchmark/Prime.Extensions.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;

namespace Prime.Extensions.Benchmarks
{
public class Program
{
public static void Main(string[] args)
{
BenchmarkSwitcher
.FromAssembly(typeof(Program).Assembly)
.Run(args, new DebugInProcessConfig());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
``` ini

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=5.0.202
[Host] : .NET Core 5.0.5 (CoreCLR 5.0.521.16609, CoreFX 5.0.521.16609), X64

```

| Method | Mean | Error | StdDev | Median | Rank | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------------------- |----------:|---------:|----------:|----------:|-----:|----------:|---------:|------:|------------:|
| FindIdsClassic200 | 10.65 ms | 0.480 ms | 1.394 ms | 10.67 ms | 1 | - | - | - | 322.7 KB |
| FindIdsOptimized200 | 10.55 ms | 0.321 ms | 0.935 ms | 10.43 ms | 1 | 46.8750 | - | - | 338.72 KB |
| FindIdsClassic1000 | 25.45 ms | 0.580 ms | 1.684 ms | 25.29 ms | 3 | 218.7500 | 62.5000 | - | 1372.31 KB |
| FindIdsOptimized1000 | 24.57 ms | 1.318 ms | 3.694 ms | 24.18 ms | 2 | 250.0000 | 93.7500 | - | 1531.93 KB |
| FindIdsClassic5000 | 141.15 ms | 8.385 ms | 24.058 ms | 139.35 ms | 5 | 1000.0000 | 500.0000 | - | 6877.5 KB |
| FindIdsOptimized5000 | 83.00 ms | 2.871 ms | 8.375 ms | 81.85 ms | 4 | 1142.8571 | 571.4286 | - | 7369.99 KB |
| FindIdsClassic10000 | 241.54 ms | 6.473 ms | 18.469 ms | 242.59 ms | 7 | 2000.0000 | 666.6667 | - | 13674.21 KB |
| FindIdsOptimized10000 | 156.01 ms | 6.863 ms | 19.910 ms | 154.24 ms | 6 | 2250.0000 | 750.0000 | - | 14622.44 KB |
15 changes: 13 additions & 2 deletions src/MongoDB.Extensions.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Session", "Session\Session.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Session.Tests", "Session.Tests\Session.Tests.csproj", "{7D953E6D-B34C-4724-8E4D-A968110CAC74}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Prime.Extensions", "Prime.Extensions\Prime.Extensions.csproj", "{284AF759-C10C-4C89-AFA3-F2D190115CC6}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prime.Extensions", "Prime.Extensions\Prime.Extensions.csproj", "{284AF759-C10C-4C89-AFA3-F2D190115CC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Prime.Extensions.Tests", "Prime.Extensions.Tests\Prime.Extensions.Tests.csproj", "{74A9A535-5E20-4453-A670-2E37A279226C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prime.Extensions.Tests", "Prime.Extensions.Tests\Prime.Extensions.Tests.csproj", "{74A9A535-5E20-4453-A670-2E37A279226C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmark", "benchmark", "{73BCA034-E71E-462C-93E7-DF956BBC5E67}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Prime.Extensions.Benchmarks", "..\benchmark\Prime.Extensions.Benchmarks\Prime.Extensions.Benchmarks.csproj", "{960D6087-8C05-4B19-B7D6-78F92F7BAA3F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -45,10 +49,17 @@ Global
{74A9A535-5E20-4453-A670-2E37A279226C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74A9A535-5E20-4453-A670-2E37A279226C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74A9A535-5E20-4453-A670-2E37A279226C}.Release|Any CPU.Build.0 = Release|Any CPU
{960D6087-8C05-4B19-B7D6-78F92F7BAA3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{960D6087-8C05-4B19-B7D6-78F92F7BAA3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{960D6087-8C05-4B19-B7D6-78F92F7BAA3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{960D6087-8C05-4B19-B7D6-78F92F7BAA3F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{960D6087-8C05-4B19-B7D6-78F92F7BAA3F} = {73BCA034-E71E-462C-93E7-DF956BBC5E67}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1C05A190-7BC9-4DE5-A49D-D7557B01869D}
EndGlobalSection
Expand Down
5 changes: 5 additions & 0 deletions src/Prime.Extensions/MongoCollectionFindExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public static async Task<IDictionary<TId, TDocument>> FindIdsAsync<TId, TDocumen
{
int allIdsCount = idsToFind.Count();

if (allIdsCount == 0)
{
return new Dictionary<TId, TDocument>();
}

Func<TDocument, TId> idSelectorFunc = idResultSelector.Compile();

int batchPartitionsCount =
Expand Down