Skip to content

Commit 55d0bc5

Browse files
Added concurrent list and updated/tweaked other collection implementations.
1 parent daae33f commit 55d0bc5

9 files changed

Lines changed: 399 additions & 197 deletions

benchmarking/Program.cs

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ internal static class Program
1414
{
1515
static void Main()
1616
{
17-
//BenchmarkRunner.Run<SubsetBenchmarks>();
17+
//BenchmarkRunner.Run<SubsetBenchmarks>();
1818

19-
//TestEntry.Test1();
20-
//TestEntry.Test2();
19+
//TestEntry.Test1();
20+
//TestEntry.Test2();
21+
//QueueTests();
2122
ListTests();
2223

2324
Console.Beep();
@@ -140,46 +141,44 @@ static void LinkedListTests()
140141
static void ListTests()
141142
{
142143
Console.WriteLine("::: Synchronized Lists :::\n");
143-
{
144-
var report = new BenchmarkConsoleReport<Func<IList<object>>>(100000, ListParallelBenchmark.Results);
145-
146-
report.AddBenchmark("TrackedList",
147-
_ => () => new TrackedList<object>());
148-
report.AddBenchmark("LockSynchronizedList",
149-
_ => () => new LockSynchronizedList<object>());
150-
report.AddBenchmark("ReadWriteSynchronizedList",
151-
_ => () => new ReadWriteSynchronizedList<object>());
152-
153-
report.Pretest(200, 200); // Run once through first to scramble/warm-up initial conditions.
154-
155-
report.Test(100, 4);
156-
report.Test(250, 4);
157-
report.Test(1000, 4);
158-
report.Test(2000, 4);
159-
report.Test(4000, 4);
160-
}
144+
var report = new BenchmarkConsoleReport<Func<IList<object>>>(100000, ListParallelBenchmark.Results);
145+
146+
report.AddBenchmark("TrackedList",
147+
_ => () => new TrackedList<object>());
148+
report.AddBenchmark("ConcurrentList",
149+
_ => () => new ConcurrentList<object>());
150+
report.AddBenchmark("LockSynchronizedList",
151+
_ => () => new LockSynchronizedList<object>());
152+
report.AddBenchmark("ReadWriteSynchronizedList",
153+
_ => () => new ReadWriteSynchronizedList<object>());
154+
155+
report.Pretest(200, 200); // Run once through first to scramble/warm-up initial conditions.
156+
157+
report.Test(100, 4);
158+
report.Test(250, 4);
159+
report.Test(1000, 4);
160+
report.Test(2000, 4);
161+
report.Test(4000, 4);
161162
}
162163

163164
static void HashSetTests()
164165
{
165166
Console.WriteLine("::: Synchronized HashSets :::\n");
166-
{
167-
var report = new BenchmarkConsoleReport<Func<ICollection<object>>>(100000, CollectionParallelBenchmark.Results);
167+
var report = new BenchmarkConsoleReport<Func<ICollection<object>>>(100000, CollectionParallelBenchmark.Results);
168168

169-
report.AddBenchmark("ConcurrentDictionary",
170-
_ => () => new ConcurrentHashSet<object>());
169+
report.AddBenchmark("ConcurrentDictionary",
170+
_ => () => new ConcurrentHashSet<object>());
171171

172-
report.AddBenchmark("LockSynchronizedHashSet",
173-
_ => () => new LockSynchronizedHashSet<object>());
174-
report.AddBenchmark("ReadWriteSynchronizedHashSet",
175-
_ => () => new ReadWriteSynchronizedHashSet<object>());
172+
report.AddBenchmark("LockSynchronizedHashSet",
173+
_ => () => new LockSynchronizedHashSet<object>());
174+
report.AddBenchmark("ReadWriteSynchronizedHashSet",
175+
_ => () => new ReadWriteSynchronizedHashSet<object>());
176176

177-
report.Pretest(200, 200); // Run once through first to scramble/warm-up initial conditions.
177+
report.Pretest(200, 200); // Run once through first to scramble/warm-up initial conditions.
178178

179-
report.Test(100, 4);
180-
report.Test(250, 4);
181-
report.Test(1000, 4 * 4);
182-
report.Test(2000, 8 * 4);
183-
}
179+
report.Test(100, 4);
180+
report.Test(250, 4);
181+
report.Test(1000, 4 * 4);
182+
report.Test(2000, 8 * 4);
184183
}
185184
}

source/CollectionWrapper.cs

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,59 @@
11
using System.Collections.Generic;
2+
using System.Runtime.CompilerServices;
23

34
namespace Open.Collections;
45

5-
public class CollectionWrapper<T, TCollection> : ReadOnlyCollectionWrapper<T, TCollection>, ICollection<T>
6+
public abstract class CollectionWrapper<T, TCollection> : ReadOnlyCollectionWrapper<T, TCollection>, ICollection<T>
67
where TCollection : class, ICollection<T>
78
{
89
protected CollectionWrapper(TCollection source) : base(source)
910
{
1011
}
1112

12-
#region Implementation of ICollection<T>
13+
#region Implementation of ICollection<T>
1314

14-
/// <inheritdoc />
15-
public virtual void Add(T item) => InternalSource.Add(item);
15+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
16+
protected virtual void AddInternal(T item)
17+
=> InternalSource.Add(item);
18+
19+
/// <inheritdoc />
20+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
21+
public virtual void Add(T item) => AddInternal(item);
1622

17-
/// <inheritdoc cref="ICollection&lt;T&gt;" />
18-
/// <param name="item1">First item to add.</param>
19-
/// <param name="item2">Additional item to add.</param>
20-
/// <param name="items">Extended param items to add.</param>
21-
public virtual void Add(T item1, T item2, params T[] items)
23+
/// <inheritdoc cref="ICollection&lt;T&gt;" />
24+
/// <param name="item1">First item to add.</param>
25+
/// <param name="item2">Additional item to add.</param>
26+
/// <param name="items">Extended param items to add.</param>
27+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
28+
public virtual void Add(T item1, T item2, params T[] items)
2229
{
23-
InternalSource.Add(item1);
24-
InternalSource.Add(item2);
30+
AddInternal(item1);
31+
AddInternal(item2);
2532
foreach (T? i in items)
26-
InternalSource.Add(i);
33+
AddInternal(i);
2734
}
2835

29-
/// <summary>
30-
/// Adds mutliple items to the collection.
31-
/// It's important to avoid locking for too long so an array is used to add multiple items.
32-
/// An enumerable is potentially slow as it may be yielding to a process.
33-
/// </summary>
34-
/// <param name="items">The items to add.</param>
35-
public virtual void AddRange(IEnumerable<T> items)
36+
/// <summary>
37+
/// Adds mutliple items to the collection.
38+
/// It's important to avoid locking for too long so an array is used to add multiple items.
39+
/// An enumerable is potentially slow as it may be yielding to a process.
40+
/// </summary>
41+
/// <param name="items">The items to add.</param>
42+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
43+
public virtual void AddRange(IEnumerable<T> items)
3644
{
37-
foreach (T? i in items)
38-
InternalSource.Add(i);
45+
foreach (var i in items)
46+
AddInternal(i);
3947
}
4048

41-
/// <inheritdoc />
42-
public virtual void Clear()
49+
/// <inheritdoc />
50+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
51+
public virtual void Clear()
4352
=> InternalSource.Clear();
4453

45-
/// <inheritdoc />
46-
public virtual bool Remove(T item)
54+
/// <inheritdoc />
55+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
56+
public virtual bool Remove(T item)
4757
=> InternalSource.Remove(item);
4858

4959
/// <inheritdoc />

source/ListWrapper.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Collections.Generic;
2+
using System.Runtime.CompilerServices;
3+
4+
namespace Open.Collections;
5+
public abstract class ListWrapper<T> : CollectionWrapper<T, IList<T>>, IList<T>
6+
{
7+
protected ListWrapper(IList<T> source) : base(source)
8+
{
9+
}
10+
11+
/// <inheritdoc />
12+
public virtual T this[int index]
13+
{
14+
get => InternalSource[index];
15+
set => InternalSource[index] = value;
16+
}
17+
18+
/// <inheritdoc />
19+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
20+
public virtual int IndexOf(T item)
21+
=> InternalSource.IndexOf(item);
22+
23+
/// <inheritdoc />
24+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
25+
public virtual void Insert(int index, T item)
26+
=> InternalSource.Insert(index, item);
27+
28+
/// <inheritdoc />
29+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30+
public virtual void RemoveAt(int index)
31+
=> InternalSource.RemoveAt(index);
32+
}

source/ReadOnlyCollectionWrapper.cs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections;
44
using System.Collections.Generic;
5+
using System.Runtime.CompilerServices;
56

67
namespace Open.Collections;
78

@@ -12,9 +13,11 @@ public class ReadOnlyCollectionWrapper<T, TCollection> : DisposableBase, IReadOn
1213

1314
protected ReadOnlyCollectionWrapper(TCollection source) => InternalSource = source ?? throw new ArgumentNullException(nameof(source));
1415

15-
#region Implementation of IReadOnlyCollection<T>
16-
/// <inheritdoc cref="ICollection&lt;T&gt;.Contains(T)" />
17-
public virtual bool Contains(T item) => InternalSource.Contains(item);
16+
#region Implementation of IReadOnlyCollection<T>
17+
/// <inheritdoc cref="ICollection&lt;T&gt;.Contains(T)" />
18+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
19+
public virtual bool Contains(T item)
20+
=> InternalSource.Contains(item);
1821

1922
/// <inheritdoc />
2023
public virtual int Count
@@ -29,19 +32,25 @@ public virtual bool IsReadOnly
2932
/// </summary>
3033
/// <returns>An enumerator from the underlying collection.</returns>
3134
// ReSharper disable once InheritdocConsiderUsage
32-
public IEnumerator<T> GetEnumerator() => InternalSource.GetEnumerator();
35+
public virtual IEnumerator<T> GetEnumerator() => InternalSource.GetEnumerator();
3336

3437
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
3538

36-
/// <inheritdoc cref="ICollection&lt;T&gt;.CopyTo(T[], int)" />
37-
public virtual void CopyTo(T[] array, int arrayIndex) => InternalSource.CopyTo(array, arrayIndex);
38-
#endregion
39+
/// <inheritdoc cref="ICollection&lt;T&gt;.CopyTo(T[], int)" />
40+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
41+
public virtual void CopyTo(T[] array, int arrayIndex)
42+
=> InternalSource.CopyTo(array, arrayIndex);
43+
#endregion
3944

40-
/// <inheritdoc cref="Extensions.CopyToSpan{T}(IEnumerable{T}, Span{T})"/>
41-
public virtual Span<T> CopyTo(Span<T> span) => InternalSource.CopyToSpan(span);
45+
/// <inheritdoc cref="Extensions.CopyToSpan{T}(IEnumerable{T}, Span{T})"/>
46+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
47+
public virtual Span<T> CopyTo(Span<T> span)
48+
=> InternalSource.CopyToSpan(span);
4249

43-
/// <inheritdoc cref="ISynchronizedCollection&lt;T&gt;.Export(ICollection{T})" />
44-
public virtual void Export(ICollection<T> to) => to.Add(InternalSource);
50+
/// <inheritdoc cref="ISynchronizedCollection&lt;T&gt;.Export(ICollection{T})" />
51+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
52+
public virtual void Export(ICollection<T> to)
53+
=> to.Add(InternalSource);
4554

4655
#region Dispose
4756
protected override void OnDispose() => Nullify(ref InternalSource)?.Dispose();

0 commit comments

Comments
 (0)