-
Notifications
You must be signed in to change notification settings - Fork 273
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding benchmarks from Akade.IndexedSet (#3410)
* Added benchmarks from Akade.IndexedSet * Updated azure-pipelines.yml * Removed NuGet.config <clear /> * Update README.md * Fix typo. --------- Co-authored-by: Jiri Cincura ↹ <[email protected]>
- Loading branch information
1 parent
2128119
commit 73a1e1d
Showing
17 changed files
with
559 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/Akade.IndexedSet.Benchmarks.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<IsTestProject>false</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>$(PERFLAB_TARGET_FRAMEWORKS)</TargetFrameworks> | ||
<TargetFrameworks Condition="'$(TargetFrameworks)' == ''">net8.0</TargetFrameworks> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Akade.IndexedSet" Version="1.0.1" /> | ||
<PackageReference Include="Bogus" Version="34.0.2" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\..\harness\BenchmarkDotNet.Extensions\BenchmarkDotNet.Extensions.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
9 changes: 9 additions & 0 deletions
9
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/Categories.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Akade.IndexedSet.Benchmarks; | ||
|
||
public static class Categories | ||
{ | ||
/// <summary> | ||
/// Benchmarks in this category are executed for CI jobs | ||
/// </summary> | ||
public const string AkadeIndexedSet = "AkadeIndexedSet"; | ||
} |
81 changes: 81 additions & 0 deletions
81
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/ConcurrentSetBenchmarks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
using Akade.IndexedSet.Concurrency; | ||
using BenchmarkDotNet.Attributes; | ||
using Bogus; | ||
|
||
namespace Akade.IndexedSet.Benchmarks; | ||
|
||
[BenchmarkCategory(Categories.AkadeIndexedSet)] | ||
public class ConcurrentSetBenchmarks | ||
{ | ||
private readonly List<Person> _persons; | ||
private readonly IndexedSet<Person> _indexedSet; | ||
private readonly ConcurrentIndexedSet<Person> _concurrentIndexedSet; | ||
|
||
public ConcurrentSetBenchmarks() | ||
{ | ||
Randomizer.Seed = new Random(42); | ||
_persons = Enumerable.Range(0, 1000) | ||
.Select(_ => new Person()) | ||
.ToList(); | ||
|
||
_indexedSet = _persons.ToIndexedSet() | ||
.WithUniqueIndex(x => x.Phone) | ||
.WithFullTextIndex(x => x.FullName) | ||
.WithRangeIndex(GetAge) | ||
.Build(); | ||
|
||
_concurrentIndexedSet = _persons.ToIndexedSet() | ||
.WithUniqueIndex(x => x.Phone) | ||
.WithFullTextIndex(x => x.FullName) | ||
.WithRangeIndex(GetAge) | ||
.BuildConcurrent(); | ||
} | ||
|
||
public static int GetAge(Person p) | ||
{ | ||
DateTime today = DateTime.Today; | ||
int age = today.Year - p.DateOfBirth.Year; | ||
|
||
if (p.DateOfBirth.Date > today.AddYears(-age)) | ||
{ | ||
age--; | ||
} | ||
return age; | ||
} | ||
|
||
[Benchmark] | ||
public bool UniqueLookup() | ||
{ | ||
return _indexedSet.TryGetSingle(x => x.Phone, "random", out _); | ||
} | ||
|
||
[Benchmark] | ||
public bool ConcurrentUniqueLookup() | ||
{ | ||
return _concurrentIndexedSet.TryGetSingle(x => x.Phone, "random", out _); | ||
} | ||
|
||
[Benchmark] | ||
public int LessThanLookup() | ||
{ | ||
return _indexedSet.LessThan(GetAge, 12).Count(); | ||
} | ||
|
||
[Benchmark] | ||
public int ConcurrentLessThanLookup() | ||
{ | ||
return _concurrentIndexedSet.LessThan(GetAge, 12).Count(); | ||
} | ||
|
||
[Benchmark] | ||
public int FullTextLookup() | ||
{ | ||
return _indexedSet.FuzzyContains(x => x.FullName, "Peter", 1).Count(); | ||
} | ||
|
||
[Benchmark] | ||
public int ConcurrentFullTextLookup() | ||
{ | ||
return _concurrentIndexedSet.FuzzyContains(x => x.FullName, "Peter", 1).Count(); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/FullTextIndexBenchmarks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using BenchmarkDotNet.Attributes; | ||
using Bogus; | ||
|
||
namespace Akade.IndexedSet.Benchmarks; | ||
|
||
[BenchmarkCategory(Categories.AkadeIndexedSet)] | ||
public class FullTextIndexBenchmarks | ||
{ | ||
public record class Document(string Content); | ||
|
||
private readonly IndexedSet<Document> _indexedSet; | ||
private readonly List<Document> _document; | ||
|
||
public FullTextIndexBenchmarks() | ||
{ | ||
Randomizer.Seed = new Random(42); | ||
_document = new Faker<Document>().CustomInstantiator(f => new Document(f.Rant.Review())) | ||
.Generate(1000); | ||
|
||
_indexedSet = _document.ToIndexedSet() | ||
.WithFullTextIndex(x => x.Content) | ||
.Build(); | ||
|
||
} | ||
|
||
[Benchmark] | ||
public Document[] Contains_IndexedSet() | ||
{ | ||
return _indexedSet.Contains(x => x.Content, "cheeseburger").ToArray(); | ||
} | ||
|
||
[Benchmark] | ||
public Document[] FuzzyContains_IndexedSet() | ||
{ | ||
return _indexedSet.FuzzyContains(x => x.Content, "cheeseburger", 2).ToArray(); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/MultiValueIndexBenchmarks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using BenchmarkDotNet.Attributes; | ||
|
||
namespace Akade.IndexedSet.Benchmarks; | ||
|
||
[BenchmarkCategory(Categories.AkadeIndexedSet)] | ||
public class MultiValueIndexBenchmarks | ||
{ | ||
private record Order(int ProductId, decimal Price); | ||
private readonly List<Order> _orders; | ||
private readonly List<int> _productIds; | ||
private readonly IndexedSet<Order> _indexedSet; | ||
|
||
public MultiValueIndexBenchmarks() | ||
{ | ||
Random r = new(42); | ||
_orders = Enumerable.Range(0, 1000) | ||
.Select(_ => new Order(r.Next(1, 10), (decimal)r.NextDouble() * 100m)) | ||
.ToList(); | ||
|
||
_productIds = Enumerable.Range(1, 10) | ||
.ToList(); | ||
|
||
_indexedSet = _orders.ToIndexedSet() | ||
.WithIndex(x => x.ProductId) | ||
.Build(); | ||
} | ||
|
||
[Benchmark] | ||
public decimal Multivalue_IndexedSet() | ||
{ | ||
decimal total = 0; | ||
foreach (int productId in _productIds) | ||
{ | ||
foreach (Order product in _indexedSet.Where(x => x.ProductId, productId)) | ||
{ | ||
total += product.Price; | ||
} | ||
} | ||
return total; | ||
} | ||
|
||
} |
35 changes: 35 additions & 0 deletions
35
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/PrefixIndexBenchmarks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using BenchmarkDotNet.Attributes; | ||
using Bogus; | ||
|
||
namespace Akade.IndexedSet.Benchmarks; | ||
|
||
[BenchmarkCategory(Categories.AkadeIndexedSet)] | ||
public class PrefixIndexBenchmarks | ||
{ | ||
private readonly List<Person> _persons; | ||
private readonly IndexedSet<Person> _indexedSet; | ||
|
||
public PrefixIndexBenchmarks() | ||
{ | ||
Randomizer.Seed = new Random(42); | ||
_persons = Enumerable.Range(0, 1000) | ||
.Select(_ => new Person()) | ||
.ToList(); | ||
|
||
_indexedSet = _persons.ToIndexedSet() | ||
.WithPrefixIndex(x => x.FullName) | ||
.Build(); | ||
} | ||
|
||
[Benchmark] | ||
public Person[] StartsWith_IndexedSet() | ||
{ | ||
return _indexedSet.StartsWith(x => x.FullName, "Tiffany").ToArray(); | ||
} | ||
|
||
[Benchmark] | ||
public Person[] FuzzyStartsWith_IndexedSet() | ||
{ | ||
return _indexedSet.FuzzyStartsWith(x => x.FullName, "Tiffany", 2).ToArray(); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/Program.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using Akade.IndexedSet.Benchmarks; | ||
using BenchmarkDotNet.Extensions; | ||
using BenchmarkDotNet.Running; | ||
using System.Collections.Immutable; | ||
|
||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, RecommendedConfig.Create( | ||
artifactsPath: new DirectoryInfo(Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location)!, "BenchmarkDotNet.Artifacts")), | ||
mandatoryCategories: ImmutableHashSet.Create(Categories.AkadeIndexedSet))); |
3 changes: 3 additions & 0 deletions
3
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Akade.IndexedSet.Benchmarks | ||
|
||
Includes benchmarks from [Akade.IndexedSet](https://github.com/akade/Akade.IndexedSet) that benchmark the library itself. Hence, all the comparison benchmarks with LINQ-based solutions are removed. |
57 changes: 57 additions & 0 deletions
57
src/benchmarks/real-world/Akade.IndexedSet.Benchmarks/RangeIndexBenchmarks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using BenchmarkDotNet.Attributes; | ||
using Bogus; | ||
|
||
namespace Akade.IndexedSet.Benchmarks; | ||
|
||
[BenchmarkCategory(Categories.AkadeIndexedSet)] | ||
public class RangeIndexBenchmarks | ||
{ | ||
private record class Appointment(DateOnly Date); | ||
|
||
private readonly IndexedSet<Appointment> _indexedSet; | ||
private readonly List<Appointment> _appointments; | ||
|
||
private readonly DateOnly _start = new(1879, 3, 14); | ||
private readonly DateOnly _end = new(1955, 4, 18); | ||
|
||
public RangeIndexBenchmarks() | ||
{ | ||
Randomizer.Seed = new Random(42); | ||
_appointments = new Faker<Appointment>().CustomInstantiator(f => new Appointment(f.Date.BetweenDateOnly(_start, _end))) | ||
.Generate(10000); | ||
|
||
_indexedSet = _appointments.ToIndexedSet() | ||
.WithRangeIndex(x => x.Date) | ||
.Build(); | ||
|
||
} | ||
|
||
|
||
[Benchmark] | ||
public int Range_IndexedSet() | ||
{ | ||
DateOnly start = _start.AddYears(10); | ||
DateOnly end = _start.AddYears(18); | ||
return _indexedSet.Range(x => x.Date, start, end).Count(); | ||
} | ||
|
||
[Benchmark] | ||
public int Paging_IndexedSet() | ||
{ | ||
return _indexedSet.OrderBy(x => x.Date, 100).Take(10).ToArray().Length; | ||
} | ||
|
||
[Benchmark] | ||
public DateOnly Min_IndexedSet() | ||
{ | ||
return _indexedSet.Min(x => x.Date); | ||
} | ||
|
||
[Benchmark] | ||
public int LessThan_IndexedSet() | ||
{ | ||
DateOnly end = _start.AddYears(10); | ||
return _indexedSet.LessThan(x => x.Date, end).Count(); | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
...ld/Akade.IndexedSet.Benchmarks/RealWorld/EventSourcedAggregateCache/AggregateAndEvents.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System.Collections.Immutable; | ||
|
||
namespace Akade.IndexedSet.Benchmarks.RealWorld.EventSourcedAggregateCache; | ||
|
||
public record class Aggregate(AggregateId Id, TenantId Owner, ImmutableHashSet<TenantId> SharedWith, ExternalAggregateId ExternalId, string FirstName, string LastName); | ||
public record struct AggregateId(long Id); | ||
public record struct TenantId(long Id); | ||
public record struct ExternalAggregateId(long PartOne, long PartTwo); | ||
|
||
public record class AggregateAdded(AggregateId Id, TenantId Owner, ExternalAggregateId ExternalId, string FirstName, string LastName) : AggregateEvent; | ||
public abstract record class AggregateEvent(); | ||
public record class AggregateShared(AggregateId Id, TenantId SharedWith) : AggregateEvent; | ||
|
||
internal static class AggregateIndices | ||
{ | ||
internal static IEnumerable<TenantId> TenantsWithAccess(Aggregate aggregate) | ||
{ | ||
return aggregate.SharedWith.Prepend(aggregate.Owner); | ||
} | ||
|
||
internal static string FullName(Aggregate aggregate) | ||
{ | ||
return $"{aggregate.FirstName} {aggregate.LastName}"; | ||
} | ||
} |
Oops, something went wrong.