Skip to content
This repository was archived by the owner on Oct 20, 2023. It is now read-only.

Commit 7a40492

Browse files
committed
Brought back the shortcut when compiling a singleton expression, changed registration store to use singlylinkedlist instead of list for the bindings for better memory performance
1 parent be2ea61 commit 7a40492

15 files changed

+161
-105
lines changed

Singularity.Benchmark/AdvancedContainerBenchmark.cs

+15-15
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ public void Setup()
1717
_benchmark = new AdvancedSingularityContainerBenchmark();
1818
}
1919

20-
[Benchmark]
21-
public void AspNetCore()
22-
{
23-
_benchmark.AspNetCore();
24-
}
20+
//[Benchmark]
21+
//public void AspNetCore()
22+
//{
23+
// _benchmark.AspNetCore();
24+
//}
2525

2626
//[Benchmark]
2727
//public ISimpleAdapter[] MultiEnumerate()
@@ -45,11 +45,11 @@ public void AspNetCore()
4545
// return _benchmark.Disposable();
4646
//}
4747

48-
//[Benchmark]
49-
//public void Register()
50-
//{
51-
// _benchmark.Register();
52-
//}
48+
[Benchmark]
49+
public void Register()
50+
{
51+
_benchmark.Register();
52+
}
5353

5454
//[Benchmark]
5555
//public void RegisterAndEnumerate()
@@ -69,11 +69,11 @@ public void AspNetCore()
6969
// return _benchmark.NewContainerFromCachedConfig();
7070
//}
7171

72-
//[Benchmark]
73-
//public IComplex1 NewContainerAndResolve()
74-
//{
75-
// return _benchmark.NewContainerAndResolve();
76-
//}
72+
[Benchmark]
73+
public IComplex1 NewContainerAndResolve()
74+
{
75+
return _benchmark.NewContainerAndResolve();
76+
}
7777

7878
//[Benchmark]
7979
//public Container NewNestedContainer()

Singularity.Benchmark/CustomJob.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ public CustomJob()
1212
Add(
1313
Job.RyuJitX64
1414
.With(Runtime.Core)
15-
.WithIterationTime(TimeInterval.FromMilliseconds(1000)));
15+
.WithIterationTime(TimeInterval.FromMilliseconds(150)));
1616

1717
Add(
1818
Job.LegacyJitX64
1919
.With(Runtime.Clr)
20-
.WithIterationTime(TimeInterval.FromMilliseconds(1000)));
20+
.WithIterationTime(TimeInterval.FromMilliseconds(150)));
2121
}
2222
}
2323
}

Singularity.Benchmark/ImmutableDictionaryBenchmarks.cs

+13-8
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,26 @@ public class ImmutableDictionaryBenchmarks
1818
[GlobalSetup]
1919
public void Setup()
2020
{
21+
_mapping = new ReferenceInt[N];
22+
for (int i = 0; i < _mapping.Length; i++)
23+
{
24+
_mapping[i] = new ReferenceInt(i);
25+
}
2126
_hashTable = ImmutableHashTable<ReferenceInt, int>.Empty;
2227
for (var i = 0; i < N; i++)
2328
{
2429
_hashTable = _hashTable.Add(_mapping[i], i);
2530
}
2631
}
2732

28-
[Benchmark]
29-
public void ImmutableHashTable_Get()
30-
{
31-
for (var i = 0; i < N; i++)
32-
{
33-
_hashTable.Get(_mapping[i]);
34-
}
35-
}
33+
//[Benchmark]
34+
//public void ImmutableHashTable_Get()
35+
//{
36+
// for (var i = 0; i < N; i++)
37+
// {
38+
// _hashTable.Get(_mapping[i]);
39+
// }
40+
//}
3641

3742
[Benchmark]
3843
public void ImmutableHashTable_Add()

Singularity.Benchmark/Program.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ static void Main()
1010
//BenchmarkRunner.Run<ImmutableDictionaryBenchmarks>();
1111
//BenchmarkRunner.Run<SimpleContainerBenchmark>();
1212
//BenchmarkRunner.Run()
13-
BenchmarkSwitcher.FromTypes(new[] {typeof(SimpleContainerBenchmark), typeof(AdvancedContainerBenchmark)}).RunAllJoined();
13+
//BenchmarkSwitcher.FromTypes(new[] {typeof(SimpleContainerBenchmark), typeof(AdvancedContainerBenchmark)}).RunAllJoined();
1414

15-
//BenchmarkRunner.Run<AdvancedContainerBenchmark>();
15+
BenchmarkRunner.Run<AdvancedContainerBenchmark>();
1616
//BenchmarkRunner.Run<DisposeListBenchmarks>();
1717
Console.ReadKey();
1818
}
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Collections.ObjectModel;
4-
using System.Linq;
5-
using System.Linq.Expressions;
2+
using Singularity.Collections;
63

74
namespace Singularity.Bindings
85
{
96
internal class ReadonlyRegistration
107
{
118
public Type[] DependencyTypes { get; }
12-
public ReadOnlyCollection<Binding> Bindings { get; }
9+
public ReadOnlyBindingCollection Bindings { get; }
1310

14-
public ReadonlyRegistration(Type[] dependencyTypes, IEnumerable<Binding> bindings)
11+
public ReadonlyRegistration(Type[] dependencyTypes, ReadOnlyBindingCollection bindings)
1512
{
1613
DependencyTypes = dependencyTypes;
17-
Bindings = new ReadOnlyCollection<Binding>(bindings.ToArray());
14+
Bindings = bindings;
1815
}
1916

2017
public ReadonlyRegistration(Type[] dependencyTypes, Binding binding)
2118
{
2219
DependencyTypes = dependencyTypes;
23-
Bindings = new ReadOnlyCollection<Binding>(new[] { binding });
20+
Bindings = new ReadOnlyBindingCollection(new SinglyLinkedListNode<Binding>(null, binding));
2421
}
2522
}
2623
}

Singularity/Bindings/Registration.cs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
using System;
22
using System.Collections.Generic;
3+
using Singularity.Collections;
34
using Singularity.Exceptions;
45

56
namespace Singularity.Bindings
67
{
78
internal class Registration
89
{
910
public Type[] DependencyTypes { get; }
10-
public List<WeaklyTypedBinding> Bindings { get; } = new List<WeaklyTypedBinding>();
11+
public SinglyLinkedListNode<WeaklyTypedBinding>? Bindings { get; set; }
1112

1213
public Registration(Type[] dependencyTypes)
1314
{
@@ -16,11 +17,12 @@ public Registration(Type[] dependencyTypes)
1617

1718
internal void Verify(List<WeaklyTypedDecoratorBinding>? decorators)
1819
{
19-
foreach (WeaklyTypedBinding weaklyTypedBinding in Bindings)
20+
SinglyLinkedListNode<WeaklyTypedBinding>? currentBinding = Bindings;
21+
while (currentBinding != null)
2022
{
21-
if (weaklyTypedBinding.Expression == null && (decorators == null || decorators!.Count == 0))
23+
if (currentBinding.Value.Expression == null && (decorators == null || decorators!.Count == 0))
2224
{
23-
throw new BindingConfigException($"The binding at {weaklyTypedBinding.BindingMetadata.StringRepresentation()} does not have a expression");
25+
throw new BindingConfigException($"The binding at {currentBinding.Value.BindingMetadata.StringRepresentation()} does not have a expression");
2426
}
2527

2628
if (decorators != null)
@@ -31,6 +33,8 @@ internal void Verify(List<WeaklyTypedDecoratorBinding>? decorators)
3133
throw new BindingConfigException($"The decorator for {DependencyTypes} does not have a expression");
3234
}
3335
}
36+
37+
currentBinding = currentBinding.Next;
3438
}
3539
}
3640
}

Singularity/Collections/HashHelpers.cs

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ internal static class HashHelpers
77
[MethodImpl(MethodImplOptions.AggressiveInlining)]
88
public static int GetHashCode(object item)
99
{
10-
//return item.GetHashCode();
1110
return RuntimeHelpers.GetHashCode(item);
1211
}
1312
}

Singularity/Collections/ImmutableHashTable.cs

+13-28
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,13 @@ internal TValue Get(TKey key)
2323
int hashCode = HashHelpers.GetHashCode(key);
2424
int bucketIndex = hashCode & (Buckets.Length - 1);
2525

26-
SinglyLinkedListNode<HashedKeyValue<TKey, TValue>> current = Buckets[bucketIndex];
26+
SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>? current = Buckets[bucketIndex];
2727

28-
do
28+
while (current != null)
2929
{
3030
if (ReferenceEquals(current.Value.Key, key)) return current.Value.Value;
3131
current = current.Next;
3232
}
33-
while (!ReferenceEquals(current, SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>.Empty));
3433

3534
return default!;
3635
}
@@ -42,8 +41,15 @@ private ImmutableHashTable(ImmutableHashTable<TKey, TValue> previous, in HashedK
4241
if (previous.Count >= previous.Buckets.Length)
4342
{
4443
this.Buckets = new SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>[previous.Buckets.Length * 2];
45-
this.AddExistingValues(previous);
46-
44+
foreach (SinglyLinkedListNode<HashedKeyValue<TKey, TValue>> t in previous.Buckets)
45+
{
46+
SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>? current = t;
47+
while (current != null)
48+
{
49+
FillBucket(in current.Value);
50+
current = current.Next;
51+
}
52+
}
4753
}
4854
else
4955
{
@@ -57,25 +63,6 @@ private ImmutableHashTable(ImmutableHashTable<TKey, TValue> previous, in HashedK
5763
FillBucket(in hashedKeyValue);
5864
}
5965

60-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
61-
private void AddExistingValues(ImmutableHashTable<TKey, TValue> previous)
62-
{
63-
for (var i = 0; i < Buckets.Length; i++)
64-
{
65-
Buckets[i] = SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>.Empty;
66-
}
67-
68-
for (var i = 0; i < previous.Buckets.Length; i++)
69-
{
70-
SinglyLinkedListNode<HashedKeyValue<TKey, TValue>> current = previous.Buckets[i];
71-
while (!ReferenceEquals(current, SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>.Empty))
72-
{
73-
FillBucket(in current.Value);
74-
current = current.Next;
75-
}
76-
}
77-
}
78-
7966
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8067
private void FillBucket(in HashedKeyValue<TKey, TValue> hashedKeyValue)
8168
{
@@ -86,16 +73,14 @@ private void FillBucket(in HashedKeyValue<TKey, TValue> hashedKeyValue)
8673
private ImmutableHashTable()
8774
{
8875
this.Buckets = new SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>[2];
89-
this.Buckets[0] = SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>.Empty;
90-
this.Buckets[1] = SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>.Empty;
9176
}
9277

9378
public IEnumerator<TValue> GetEnumerator()
9479
{
9580
foreach (SinglyLinkedListNode<HashedKeyValue<TKey, TValue>> bucket in Buckets)
9681
{
97-
SinglyLinkedListNode<HashedKeyValue<TKey, TValue>> current = bucket;
98-
while (!ReferenceEquals(current, SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>.Empty))
82+
SinglyLinkedListNode<HashedKeyValue<TKey, TValue>>? current = bucket;
83+
while (current != null)
9984
{
10085
yield return current.Value.Value;
10186
current = current.Next;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
4+
namespace Singularity.Collections
5+
{
6+
internal class ReadOnlyBindingCollection : IEnumerable<Binding>
7+
{
8+
private readonly SinglyLinkedListNode<Binding>? _bindings;
9+
public ReadOnlyBindingCollection(SinglyLinkedListNode<Binding>? bindings)
10+
{
11+
_bindings = bindings;
12+
}
13+
14+
public ReadOnlyBindingCollection(IEnumerable<Binding> bindings)
15+
{
16+
SinglyLinkedListNode<Binding>? previous = null;
17+
foreach (Binding binding in bindings)
18+
{
19+
previous = new SinglyLinkedListNode<Binding>(previous, binding);
20+
}
21+
_bindings = previous;
22+
}
23+
24+
public IEnumerator<Binding> GetEnumerator()
25+
{
26+
if(_bindings == null) yield break;
27+
SinglyLinkedListNode<Binding>? current = _bindings;
28+
while (current != null)
29+
{
30+
yield return current.Value;
31+
current = current.Next;
32+
}
33+
}
34+
35+
IEnumerator IEnumerable.GetEnumerator()
36+
{
37+
return GetEnumerator();
38+
}
39+
}
40+
}

Singularity/Collections/RegistrationStore.cs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections;
32
using System.Collections.Generic;
43
using System.Collections.ObjectModel;
54
using System.Linq;
@@ -38,15 +37,15 @@ public WeaklyTypedBinding CreateBinding(Type[] dependencyTypes, string callerFil
3837
Registration registration = GetOrCreateRegistration(dependencyTypes);
3938

4039
var binding = new WeaklyTypedBinding(dependencyTypes, callerFilePath, callerLineNumber, CurrentModule);
41-
registration.Bindings.Add(binding);
40+
registration.Bindings = new SinglyLinkedListNode<WeaklyTypedBinding>(registration.Bindings, binding);
4241
return binding;
4342
}
4443

4544
public ReadOnlyBindingConfig GetDependencies()
4645
{
4746
if (_readonlyBindings == null)
4847
{
49-
var uniqueRegistrations = Registrations.Values.Distinct().ToArray();
48+
Registration[] uniqueRegistrations = Registrations.Values.Distinct().ToArray();
5049
var registrations = new ReadonlyRegistration[uniqueRegistrations.Length];
5150
var count = 0;
5251
foreach (Registration registration in uniqueRegistrations)
@@ -63,7 +62,7 @@ public ReadOnlyBindingConfig GetDependencies()
6362
}
6463
}
6564

66-
registrations[count] = new ReadonlyRegistration(registration.DependencyTypes, registration.Bindings.Select(x => new Binding(x)));
65+
registrations[count] = new ReadonlyRegistration(registration.DependencyTypes, new ReadOnlyBindingCollection(registration.Bindings.Select(x => new Binding(x))));
6766
count++;
6867
}
6968

Original file line numberDiff line numberDiff line change
@@ -1,19 +1,33 @@
1-
namespace Singularity.Collections
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
5+
namespace Singularity.Collections
26
{
3-
internal sealed class SinglyLinkedListNode<T>
7+
internal sealed class SinglyLinkedListNode<T> : IEnumerable<T>
48
{
5-
public static readonly SinglyLinkedListNode<T> Empty = new SinglyLinkedListNode<T>();
69
public readonly T Value;
7-
public readonly SinglyLinkedListNode<T> Next;
10+
public readonly SinglyLinkedListNode<T>? Next;
811

9-
private SinglyLinkedListNode()
10-
{
11-
Next = this;
12-
}
13-
public SinglyLinkedListNode(SinglyLinkedListNode<T> next, in T value)
12+
public SinglyLinkedListNode(SinglyLinkedListNode<T>? next, in T value)
1413
{
1514
Next = next;
1615
Value = value;
1716
}
17+
18+
public IEnumerator<T> GetEnumerator()
19+
{
20+
SinglyLinkedListNode<T>? current = this;
21+
while (current != null)
22+
{
23+
yield return current.Value;
24+
current = current.Next;
25+
}
26+
}
27+
28+
IEnumerator IEnumerable.GetEnumerator()
29+
{
30+
return GetEnumerator();
31+
}
1832
}
1933
}

0 commit comments

Comments
 (0)