Skip to content

Commit 1a7c1b8

Browse files
committed
Remove "SingleItem.Collection()" because array is fast enough
1 parent 28be99b commit 1a7c1b8

18 files changed

+169
-240
lines changed

samples/Benchmarking/Benchmarks/ItemSearch.cs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,32 @@ namespace Thinktecture.Benchmarks;
1010

1111
/*
1212
13-
22.01.2025
14-
15-
.NET 9.0.1
16-
17-
| Method | SearchTerm | Mean | Error | StdDev | Median | Allocated |
18-
|-------------------------- |----------- |----------:|----------:|----------:|----------:|----------:|
19-
| Dictionary | aaaaAaaaaa | 16.693 ns | 1.1213 ns | 3.3061 ns | 17.322 ns | - |
20-
| FrozenDictionary | aaaaAaaaaa | 6.703 ns | 0.1758 ns | 0.1644 ns | 6.683 ns | - |
21-
| ReadOnlyDictionary | aaaaAaaaaa | 12.893 ns | 0.3104 ns | 0.6341 ns | 12.690 ns | - |
22-
| ImmutableDictionary | aaaaAaaaaa | 17.369 ns | 0.2967 ns | 0.2478 ns | 17.365 ns | - |
23-
| ImmutableSortedDictionary | aaaaAaaaaa | 17.929 ns | 0.4007 ns | 0.9601 ns | 17.715 ns | - |
24-
| ArrayIteration | aaaaAaaaaa | 2.973 ns | 0.1116 ns | 0.1044 ns | 2.937 ns | - |
25-
26-
| Dictionary | iiiiIiiiii | 9.904 ns | 0.2482 ns | 0.2438 ns | 9.821 ns | - |
27-
| FrozenDictionary | iiiiIiiiii | 7.024 ns | 0.1959 ns | 0.5363 ns | 6.867 ns | - |
28-
| ReadOnlyDictionary | iiiiIiiiii | 12.080 ns | 0.2953 ns | 0.6544 ns | 11.967 ns | - |
29-
| ImmutableDictionary | iiiiIiiiii | 17.562 ns | 0.3981 ns | 0.7280 ns | 17.336 ns | - |
30-
| ImmutableSortedDictionary | iiiiIiiiii | 22.474 ns | 0.4374 ns | 0.7064 ns | 22.262 ns | - |
31-
| ArrayIteration | iiiiIiiiii | 21.703 ns | 0.4796 ns | 0.6402 ns | 21.619 ns | - |
32-
33-
| Dictionary | tttttTtttt | 9.533 ns | 0.2432 ns | 0.3928 ns | 9.524 ns | - |
34-
| FrozenDictionary | tttttTtttt | 6.943 ns | 0.1874 ns | 0.2370 ns | 6.945 ns | - |
35-
| ReadOnlyDictionary | tttttTtttt | 11.460 ns | 0.2830 ns | 0.4570 ns | 11.473 ns | - |
36-
| ImmutableDictionary | tttttTtttt | 17.708 ns | 0.3967 ns | 0.4245 ns | 17.626 ns | - |
37-
| ImmutableSortedDictionary | tttttTtttt | 23.327 ns | 0.5152 ns | 1.5030 ns | 22.802 ns | - |
38-
| ArrayIteration | tttttTtttt | 47.615 ns | 0.9459 ns | 0.9714 ns | 47.931 ns | - |
39-
13+
29.04.2025
14+
15+
.NET 9.0.4
16+
17+
| Method | SearchTerm | Mean | Error | StdDev | Allocated |
18+
|-------------------------- |----------- |----------:|----------:|----------:|----------:|
19+
| Dictionary | aaaaAaaaaa | 9.662 ns | 0.2411 ns | 0.3380 ns | - |
20+
| FrozenDictionary | aaaaAaaaaa | 6.492 ns | 0.1784 ns | 0.2615 ns | - |
21+
| ReadOnlyDictionary | aaaaAaaaaa | 11.174 ns | 0.0698 ns | 0.0583 ns | - |
22+
| ImmutableDictionary | aaaaAaaaaa | 15.708 ns | 0.1943 ns | 0.1817 ns | - |
23+
| ImmutableSortedDictionary | aaaaAaaaaa | 17.891 ns | 0.4092 ns | 0.8078 ns | - |
24+
| ArrayIteration | aaaaAaaaaa | 2.658 ns | 0.1031 ns | 0.1666 ns | - |
25+
26+
| Dictionary | iiiiIiiiii | 9.338 ns | 0.2343 ns | 0.2406 ns | - |
27+
| FrozenDictionary | iiiiIiiiii | 6.558 ns | 0.1823 ns | 0.2238 ns | - |
28+
| ReadOnlyDictionary | iiiiIiiiii | 10.186 ns | 0.2542 ns | 0.2927 ns | - |
29+
| ImmutableDictionary | iiiiIiiiii | 15.271 ns | 0.3567 ns | 0.3663 ns | - |
30+
| ImmutableSortedDictionary | iiiiIiiiii | 20.448 ns | 0.4550 ns | 0.7217 ns | - |
31+
| ArrayIteration | iiiiIiiiii | 19.685 ns | 0.4388 ns | 0.5706 ns | - |
32+
33+
| Dictionary | tttttTtttt | 9.221 ns | 0.2357 ns | 0.3670 ns | - |
34+
| FrozenDictionary | tttttTtttt | 6.200 ns | 0.1754 ns | 0.4464 ns | - |
35+
| ReadOnlyDictionary | tttttTtttt | 10.563 ns | 0.1320 ns | 0.1235 ns | - |
36+
| ImmutableDictionary | tttttTtttt | 17.622 ns | 0.4002 ns | 0.7899 ns | - |
37+
| ImmutableSortedDictionary | tttttTtttt | 21.024 ns | 0.2958 ns | 0.2470 ns | - |
38+
| ArrayIteration | tttttTtttt | 44.569 ns | 0.9428 ns | 1.7708 ns | - |
4039
4140
*/
4241

samples/Benchmarking/Benchmarks/LoadingSmartEnums.cs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ namespace Thinktecture.Benchmarks;
1010

1111
/*
1212
13-
15.04.2025
13+
29.04.2025
1414
1515
.NET 9.0.4
1616
17-
| Method | Mean | Error | StdDev | Median | Allocated |
18-
|----------------------------- |---------:|---------:|----------:|----------:|----------:|
19-
| Real_Enum_StringConverter | 11.34 ms | 1.382 ms | 3.876 ms | 9.640 ms | 7.16 MB |
20-
| SmartEnum_Struct_StringBased | 11.63 ms | 1.485 ms | 4.214 ms | 10.541 ms | 8.51 MB |
21-
| SmartEnum_Class_StringBased | 15.93 ms | 2.599 ms | 7.416 ms | 13.270 ms | 8.21 MB |
22-
| Real_Enum_IntBased | 15.07 ms | 2.923 ms | 8.574 ms | 11.595 ms | 6.67 MB |
23-
| SmartEnum_Struct_IntBased | 16.91 ms | 4.670 ms | 13.399 ms | 10.216 ms | 8.02 MB |
24-
| SmartEnum_Class_IntBased | 20.11 ms | 5.255 ms | 15.078 ms | 12.856 ms | 7.72 MB |
17+
| Method | Mean | Error | StdDev | Median | Allocated |
18+
|---------------------------- |----------:|----------:|---------:|----------:|----------:|
19+
| RegularEnum_StringConverter | 13.255 ms | 2.0776 ms | 5.792 ms | 11.534 ms | 7.16 MB |
20+
| SmartEnum_StringBased | 10.681 ms | 1.2877 ms | 3.611 ms | 9.393 ms | 8.21 MB |
21+
| RegularEnum_IntBased | 6.979 ms | 0.7776 ms | 2.168 ms | 6.708 ms | 6.67 MB |
22+
| SmartEnum_IntBased | 8.175 ms | 1.1949 ms | 3.210 ms | 7.129 ms | 7.72 MB |
23+
24+
2525
2626
2727
*/
@@ -36,14 +36,14 @@ public class LoadingSmartEnums
3636
private const int _NUMBER_OF_ENTITIES = 10_000;
3737
private static readonly RealEnum[] _enums = Enum.GetValues<RealEnum>();
3838

39-
private readonly Entity_Enum_StringConverter[] _Entity_Enum_StringConverter
40-
= Enumerable.Range(1, _NUMBER_OF_ENTITIES).Select(i => new Entity_Enum_StringConverter(i, _enums[i % _enums.Length]) { Enum = RealEnum.Value1 }).ToArray();
41-
private readonly Entity_Enum_IntBased[] _Entity_Enum_IntBased
42-
= Enumerable.Range(1, _NUMBER_OF_ENTITIES).Select(i => new Entity_Enum_IntBased(i, _enums[i % _enums.Length]) { Enum = RealEnum.Value1 }).ToArray();
43-
private readonly Entity_SmartEnum_Class_StringBased[] _Entity_SmartEnum_Class_StringBased
44-
= Enumerable.Range(1, _NUMBER_OF_ENTITIES).Select(i => new Entity_SmartEnum_Class_StringBased(i, TestSmartEnum_Class_StringBased.Items[i % _enums.Length]) { Enum = TestSmartEnum_Class_StringBased.Value1 }).ToArray();
45-
private readonly Entity_SmartEnum_Class_IntBased[] _Entity_SmartEnum_Class_IntBased
46-
= Enumerable.Range(1, _NUMBER_OF_ENTITIES).Select(i => new Entity_SmartEnum_Class_IntBased(i, TestSmartEnum_Class_IntBased.Items[i % _enums.Length]) { Enum = TestSmartEnum_Class_IntBased.Value1 }).ToArray();
39+
private readonly Entity_RegularEnum_StringConverter[] _Entity_Enum_StringConverter
40+
= Enumerable.Range(1, _NUMBER_OF_ENTITIES).Select(i => new Entity_RegularEnum_StringConverter(i, _enums[i % _enums.Length]) { Enum = RealEnum.Value1 }).ToArray();
41+
private readonly Entity_RegularEnum_IntBased[] _Entity_Enum_IntBased
42+
= Enumerable.Range(1, _NUMBER_OF_ENTITIES).Select(i => new Entity_RegularEnum_IntBased(i, _enums[i % _enums.Length]) { Enum = RealEnum.Value1 }).ToArray();
43+
private readonly Entity_SmartEnum_StringBased[] _Entity_SmartEnum_Class_StringBased
44+
= Enumerable.Range(1, _NUMBER_OF_ENTITIES).Select(i => new Entity_SmartEnum_StringBased(i, TestSmartEnum_Class_StringBased.Items[i % _enums.Length]) { Enum = TestSmartEnum_Class_StringBased.Value1 }).ToArray();
45+
private readonly Entity_SmartEnum_IntBased[] _Entity_SmartEnum_Class_IntBased
46+
= Enumerable.Range(1, _NUMBER_OF_ENTITIES).Select(i => new Entity_SmartEnum_IntBased(i, TestSmartEnum_Class_IntBased.Items[i % _enums.Length]) { Enum = TestSmartEnum_Class_IntBased.Value1 }).ToArray();
4747

4848
[GlobalSetup]
4949
public void Initialize()
@@ -55,17 +55,17 @@ public void Initialize()
5555
_dbContext.Database.OpenConnection();
5656
_dbContext.Database.EnsureCreated();
5757

58-
_dbContext.RemoveRange(_dbContext.Entity_Enum_StringConverter);
59-
_dbContext.Entity_Enum_StringConverter.AddRange(_Entity_Enum_StringConverter);
58+
_dbContext.RemoveRange(_dbContext.Entity_RegularEnum_StringConverter);
59+
_dbContext.Entity_RegularEnum_StringConverter.AddRange(_Entity_Enum_StringConverter);
6060

61-
_dbContext.RemoveRange(_dbContext.Entity_Enum_IntBased);
62-
_dbContext.Entity_Enum_IntBased.AddRange(_Entity_Enum_IntBased);
61+
_dbContext.RemoveRange(_dbContext.Entity_RegularEnum_IntBased);
62+
_dbContext.Entity_RegularEnum_IntBased.AddRange(_Entity_Enum_IntBased);
6363

64-
_dbContext.RemoveRange(_dbContext.Entity_SmartEnum_Class_StringBased);
65-
_dbContext.Entity_SmartEnum_Class_StringBased.AddRange(_Entity_SmartEnum_Class_StringBased);
64+
_dbContext.RemoveRange(_dbContext.Entity_SmartEnum_StringBased);
65+
_dbContext.Entity_SmartEnum_StringBased.AddRange(_Entity_SmartEnum_Class_StringBased);
6666

67-
_dbContext.RemoveRange(_dbContext.Entity_SmartEnum_Class_IntBased);
68-
_dbContext.Entity_SmartEnum_Class_IntBased.AddRange(_Entity_SmartEnum_Class_IntBased);
67+
_dbContext.RemoveRange(_dbContext.Entity_SmartEnum_IntBased);
68+
_dbContext.Entity_SmartEnum_IntBased.AddRange(_Entity_SmartEnum_Class_IntBased);
6969

7070
_dbContext.SaveChanges();
7171
}
@@ -84,26 +84,26 @@ public void Dispose()
8484
}
8585

8686
[Benchmark]
87-
public async Task Real_Enum_StringConverter()
87+
public async Task RegularEnum_StringConverter()
8888
{
89-
await _dbContext!.Entity_Enum_StringConverter.ToListAsync();
89+
await _dbContext!.Entity_RegularEnum_StringConverter.ToListAsync();
9090
}
9191

9292
[Benchmark]
93-
public async Task SmartEnum_Class_StringBased()
93+
public async Task SmartEnum_StringBased()
9494
{
95-
await _dbContext!.Entity_SmartEnum_Class_StringBased.ToListAsync();
95+
await _dbContext!.Entity_SmartEnum_StringBased.ToListAsync();
9696
}
9797

9898
[Benchmark]
99-
public async Task Real_Enum_IntBased()
99+
public async Task RegularEnum_IntBased()
100100
{
101-
await _dbContext!.Entity_Enum_IntBased.ToListAsync();
101+
await _dbContext!.Entity_RegularEnum_IntBased.ToListAsync();
102102
}
103103

104104
[Benchmark]
105-
public async Task SmartEnum_Class_IntBased()
105+
public async Task SmartEnum_IntBased()
106106
{
107-
await _dbContext!.Entity_SmartEnum_Class_IntBased.ToListAsync();
107+
await _dbContext!.Entity_SmartEnum_IntBased.ToListAsync();
108108
}
109109
}

samples/Benchmarking/Benchmarks/LoadingValueObjects.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ namespace Thinktecture.Benchmarks;
99

1010
/*
1111
12-
15.04.2025
12+
29.04.2025
1313
1414
.NET 9.0.4
1515
1616
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
1717
|------------------------------- |---------:|--------:|---------:|----------:|----------:|----------:|
18-
| Entity_with_ValueObjects | 180.7 ms | 6.46 ms | 18.53 ms | 4000.0000 | 3000.0000 | 84.38 MB |
19-
| Entity_without_ValueObjects | 143.0 ms | 5.76 ms | 16.97 ms | 3000.0000 | 2000.0000 | 79.8 MB |
20-
| Entity_with_StructValueObjects | 134.2 ms | 4.16 ms | 12.26 ms | 3000.0000 | 2000.0000 | 87.86 MB |
18+
| Entity_without_ValueObjects | 148.3 ms | 4.80 ms | 13.46 ms | 3000.0000 | 2000.0000 | 79.8 MB |
19+
| Entity_with_StructValueObjects | 158.2 ms | 5.80 ms | 16.56 ms | 3000.0000 | 2000.0000 | 87.86 MB |
20+
| Entity_with_ClassValueObjects | 195.2 ms | 8.42 ms | 23.89 ms | 4000.0000 | 3000.0000 | 84.38 MB |
2121
2222
*/
2323

@@ -81,12 +81,6 @@ public void Dispose()
8181
_benchmarkContext?.Dispose();
8282
}
8383

84-
[Benchmark]
85-
public async Task Entity_with_ValueObjects()
86-
{
87-
await _dbContext!.Entity_with_ValueObjects.ToListAsync();
88-
}
89-
9084
[Benchmark]
9185
public async Task Entity_without_ValueObjects()
9286
{
@@ -98,4 +92,10 @@ public async Task Entity_with_StructValueObjects()
9892
{
9993
await _dbContext!.Entity_with_StructValueObjects.ToListAsync();
10094
}
95+
96+
[Benchmark]
97+
public async Task Entity_with_ClassValueObjects()
98+
{
99+
await _dbContext!.Entity_with_ValueObjects.ToListAsync();
100+
}
101101
}

samples/Benchmarking/Benchmarks/SingleItemCollectionBenchmarks.cs

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Collections.Generic;
2+
using BenchmarkDotNet.Attributes;
3+
4+
namespace Thinktecture.Benchmarks;
5+
6+
/*
7+
8+
29.04.2025
9+
10+
.NET 9.0.4
11+
12+
| Method | Mean | Error | StdDev | Median | Gen0 | Allocated |
13+
|---------------------------- |---------:|----------:|----------:|---------:|-------:|----------:|
14+
| ForeachSingleItemDictionary | 1.888 ns | 0.0387 ns | 0.0323 ns | 1.886 ns | 0.0017 | 32 B |
15+
| ForeachDictionary | 4.386 ns | 0.1154 ns | 0.2720 ns | 4.276 ns | 0.0025 | 48 B |
16+
17+
*/
18+
19+
public class SingleItemDictionaryBenchmarks
20+
{
21+
private readonly IReadOnlyDictionary<int, int> _singleItemSet = SingleItem.Dictionary(42, 42);
22+
private readonly IReadOnlyDictionary<int, int> _hashset = new Dictionary<int, int> { { 42, 42 } };
23+
24+
[Benchmark]
25+
public void ForeachSingleItemDictionary()
26+
{
27+
foreach (var _ in _singleItemSet)
28+
{
29+
}
30+
}
31+
32+
[Benchmark]
33+
public void ForeachDictionary()
34+
{
35+
foreach (var _ in _hashset)
36+
{
37+
}
38+
}
39+
}

samples/Benchmarking/Benchmarks/SingleItemSetBenchmarks.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@
33

44
namespace Thinktecture.Benchmarks;
55

6+
/*
7+
8+
29.04.2025
9+
10+
.NET 9.0.4
11+
12+
| Method | Mean | Error | StdDev | Gen0 | Allocated |
13+
|--------------------- |---------:|----------:|----------:|-------:|----------:|
14+
| ForeachSingleItemSet | 1.440 ns | 0.0663 ns | 0.0992 ns | 0.0013 | 24 B |
15+
| ForeachHashSet | 3.935 ns | 0.1010 ns | 0.0992 ns | 0.0021 | 40 B |
16+
17+
*/
18+
619
public class SingleItemSetBenchmarks
720
{
821
private readonly IReadOnlySet<int> _singleItemSet = SingleItem.Set(42);

samples/Benchmarking/Benchmarks/TypedIdBenchmarks.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,23 @@ namespace Thinktecture.Benchmarks;
55

66
/*
77
8-
22.01.2025
8+
29.04.2025
99
10-
.NET 9.0.1
10+
.NET 9.0.4
1111
12-
| Method | Mean | Error | StdDev | Median | Allocated |
13-
|----------------- |---------:|---------:|---------:|---------:|----------:|
14-
| Guid_NewGuid | 56.12 ns | 2.936 ns | 8.658 ns | 59.00 ns | - |
15-
| CustomerId_NewId | 41.61 ns | 0.861 ns | 1.024 ns | 41.94 ns | - |
12+
| Method | Mean | Error | StdDev | Allocated |
13+
|-------------------- |---------:|---------:|---------:|----------:|
14+
| Guid_CreateVersion7 | 54.24 ns | 0.398 ns | 0.372 ns | - |
15+
| CustomerId_NewId | 57.59 ns | 0.188 ns | 0.176 ns | - |
1616
1717
*/
1818

1919
public class TypedIdBenchmarks
2020
{
2121
[Benchmark]
22-
public Guid Guid_NewGuid()
22+
public Guid Guid_CreateVersion7()
2323
{
24-
return Guid.NewGuid();
24+
return Guid.CreateVersion7();
2525
}
2626

2727
[Benchmark]
@@ -34,5 +34,5 @@ public CustomerId CustomerId_NewId()
3434
[ValueObject<Guid>(ConversionToKeyMemberType = ConversionOperatorsGeneration.Explicit)]
3535
public partial struct CustomerId
3636
{
37-
public static CustomerId NewId() => new(Guid.NewGuid());
37+
public static CustomerId NewId() => new(Guid.CreateVersion7());
3838
}

samples/Benchmarking/Database/BenchmarkDbContext.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ namespace Thinktecture.Database;
55
// ReSharper disable InconsistentNaming
66
public class BenchmarkDbContext : DbContext
77
{
8-
public DbSet<Entity_Enum_StringConverter> Entity_Enum_StringConverter { get; set; } = null!;
9-
public DbSet<Entity_Enum_IntBased> Entity_Enum_IntBased { get; set; } = null!;
10-
public DbSet<Entity_SmartEnum_Class_StringBased> Entity_SmartEnum_Class_StringBased { get; set; } = null!;
11-
public DbSet<Entity_SmartEnum_Class_IntBased> Entity_SmartEnum_Class_IntBased { get; set; } = null!;
8+
public DbSet<Entity_RegularEnum_StringConverter> Entity_RegularEnum_StringConverter { get; set; } = null!;
9+
public DbSet<Entity_RegularEnum_IntBased> Entity_RegularEnum_IntBased { get; set; } = null!;
10+
public DbSet<Entity_SmartEnum_StringBased> Entity_SmartEnum_StringBased { get; set; } = null!;
11+
public DbSet<Entity_SmartEnum_IntBased> Entity_SmartEnum_IntBased { get; set; } = null!;
1212

1313
public DbSet<Entity_with_ValueObjects> Entity_with_ValueObjects { get; set; } = null!;
1414
public DbSet<Entity_without_ValueObjects> Entity_without_ValueObjects { get; set; } = null!;
@@ -21,21 +21,21 @@ public BenchmarkDbContext(DbContextOptions<BenchmarkDbContext> options)
2121

2222
protected override void OnModelCreating(ModelBuilder modelBuilder)
2323
{
24-
modelBuilder.Entity<Entity_Enum_StringConverter>(builder =>
24+
modelBuilder.Entity<Entity_RegularEnum_StringConverter>(builder =>
2525
{
2626
builder.Property(e => e.Id).ValueGeneratedNever();
2727
builder.Property(e => e.Enum).HasConversion<string>().HasMaxLength(20);
2828
});
2929

30-
modelBuilder.Entity<Entity_Enum_IntBased>(builder => builder.Property(e => e.Id).ValueGeneratedNever());
30+
modelBuilder.Entity<Entity_RegularEnum_IntBased>(builder => builder.Property(e => e.Id).ValueGeneratedNever());
3131

32-
modelBuilder.Entity<Entity_SmartEnum_Class_StringBased>(builder =>
32+
modelBuilder.Entity<Entity_SmartEnum_StringBased>(builder =>
3333
{
3434
builder.Property(e => e.Id).ValueGeneratedNever();
3535
builder.Property(e => e.Enum).HasMaxLength(20);
3636
});
3737

38-
modelBuilder.Entity<Entity_SmartEnum_Class_IntBased>(builder => builder.Property(e => e.Id).ValueGeneratedNever());
38+
modelBuilder.Entity<Entity_SmartEnum_IntBased>(builder => builder.Property(e => e.Id).ValueGeneratedNever());
3939

4040
modelBuilder.Entity<Entity_with_ValueObjects>(builder =>
4141
{

0 commit comments

Comments
 (0)