Skip to content

Commit daae33f

Browse files
Performance tweaks.
1 parent e25f1b1 commit daae33f

6 files changed

Lines changed: 294 additions & 219 deletions

File tree

benchmarking/Program.cs

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ static void Main()
1818

1919
//TestEntry.Test1();
2020
//TestEntry.Test2();
21-
CollectionTests();
21+
ListTests();
2222

2323
Console.Beep();
2424
}
@@ -121,29 +121,31 @@ static void LinkedListTests()
121121
*/
122122
}
123123

124-
static void CollectionTests()
125-
{
126-
//{
127-
// var report = new BenchmarkConsoleReport<Func<ICollection<object>>>(1600000, (c, r, p) => CollectionBenchmark.Results(c, r, p));
128-
129-
// report.AddBenchmark("LinkedList",
130-
// count => () => new LinkedList<object>());
131-
// report.AddBenchmark("HashSet",
132-
// count => () => new HashSet<object>());
133-
// report.AddBenchmark("List",
134-
// count => () => new List<object>());
135-
// report.Pretest(200, 200); // Run once through first to scramble/warm-up initial conditions.
136-
137-
// report.Test(100);
138-
// report.Test(250);
139-
// report.Test(1000);
140-
//}
124+
//{
125+
// var report = new BenchmarkConsoleReport<Func<ICollection<object>>>(1600000, (c, r, p) => CollectionBenchmark.Results(c, r, p));
126+
127+
// report.AddBenchmark("LinkedList",
128+
// count => () => new LinkedList<object>());
129+
// report.AddBenchmark("HashSet",
130+
// count => () => new HashSet<object>());
131+
// report.AddBenchmark("List",
132+
// count => () => new List<object>());
133+
// report.Pretest(200, 200); // Run once through first to scramble/warm-up initial conditions.
134+
135+
// report.Test(100);
136+
// report.Test(250);
137+
// report.Test(1000);
138+
//}
141139

140+
static void ListTests()
141+
{
142142
Console.WriteLine("::: Synchronized Lists :::\n");
143143
{
144144
var report = new BenchmarkConsoleReport<Func<IList<object>>>(100000, ListParallelBenchmark.Results);
145145

146-
report.AddBenchmark("LockSynchronizedList",
146+
report.AddBenchmark("TrackedList",
147+
_ => () => new TrackedList<object>());
148+
report.AddBenchmark("LockSynchronizedList",
147149
_ => () => new LockSynchronizedList<object>());
148150
report.AddBenchmark("ReadWriteSynchronizedList",
149151
_ => () => new ReadWriteSynchronizedList<object>());
@@ -154,26 +156,30 @@ static void CollectionTests()
154156
report.Test(250, 4);
155157
report.Test(1000, 4);
156158
report.Test(2000, 4);
157-
}
159+
report.Test(4000, 4);
160+
}
161+
}
158162

159-
Console.WriteLine("::: Synchronized HashSets :::\n");
160-
{
161-
var report = new BenchmarkConsoleReport<Func<ICollection<object>>>(100000, CollectionParallelBenchmark.Results);
163+
static void HashSetTests()
164+
{
165+
Console.WriteLine("::: Synchronized HashSets :::\n");
166+
{
167+
var report = new BenchmarkConsoleReport<Func<ICollection<object>>>(100000, CollectionParallelBenchmark.Results);
162168

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

166-
report.AddBenchmark("LockSynchronizedHashSet",
167-
_ => () => new LockSynchronizedHashSet<object>());
168-
report.AddBenchmark("ReadWriteSynchronizedHashSet",
169-
_ => () => new ReadWriteSynchronizedHashSet<object>());
172+
report.AddBenchmark("LockSynchronizedHashSet",
173+
_ => () => new LockSynchronizedHashSet<object>());
174+
report.AddBenchmark("ReadWriteSynchronizedHashSet",
175+
_ => () => new ReadWriteSynchronizedHashSet<object>());
170176

171-
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.
172178

173-
report.Test(100, 4);
174-
report.Test(250, 4);
175-
report.Test(1000, 4 * 4);
176-
report.Test(2000, 8 * 4);
177-
}
178-
}
179+
report.Test(100, 4);
180+
report.Test(250, 4);
181+
report.Test(1000, 4 * 4);
182+
report.Test(2000, 8 * 4);
183+
}
184+
}
179185
}

source/CollectionWrapper.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,19 @@ public virtual void Add(T item1, T item2, params T[] items)
3232
/// An enumerable is potentially slow as it may be yielding to a process.
3333
/// </summary>
3434
/// <param name="items">The items to add.</param>
35-
public virtual void Add(T[] items)
35+
public virtual void AddRange(IEnumerable<T> items)
3636
{
37-
foreach (T? i in items)
37+
foreach (T? i in items)
3838
InternalSource.Add(i);
3939
}
4040

4141
/// <inheritdoc />
42-
public virtual void Clear() => InternalSource.Clear();
42+
public virtual void Clear()
43+
=> InternalSource.Clear();
4344

4445
/// <inheritdoc />
45-
public virtual bool Remove(T item) => InternalSource.Remove(item);
46+
public virtual bool Remove(T item)
47+
=> InternalSource.Remove(item);
4648

4749
/// <inheritdoc />
4850
public override bool IsReadOnly

source/Synchronized/LockSynchronizedCollectionWrapper.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Linq;
45

56
namespace Open.Collections.Synchronized;
@@ -37,9 +38,20 @@ public override void Add(T item1, T item2, params T[] items)
3738
}
3839

3940
/// <inheritdoc />
40-
public override void Add(T[] items)
41+
public override void AddRange(IEnumerable<T> items)
4142
{
42-
lock (Sync)
43+
if (items is null) return;
44+
IReadOnlyList<T> enumerable = items switch
45+
{
46+
IImmutableList<T> i => i,
47+
T[] a => a,
48+
_ => items.ToArray(),
49+
};
50+
51+
if (enumerable.Count == 0)
52+
return;
53+
54+
lock (Sync)
4355
{
4456
foreach (T? i in items)
4557
InternalSource.Add(i);

source/Synchronized/ReadWriteSynchronizedCollectionWrapper.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
using Open.Threading;
22
using System;
33
using System.Collections.Generic;
4+
using System.Collections.Immutable;
45
using System.Linq;
56
using System.Threading;
67

78
namespace Open.Collections.Synchronized;
89

9-
public class ReadWriteSynchronizedCollectionWrapper<T, TCollection> : CollectionWrapper<T, TCollection>, ISynchronizedCollectionWrapper<T, TCollection>
10+
public class ReadWriteSynchronizedCollectionWrapper<T, TCollection>
11+
: CollectionWrapper<T, TCollection>, ISynchronizedCollectionWrapper<T, TCollection>
1012
where TCollection : class, ICollection<T>
1113
{
1214
protected ReaderWriterLockSlim Sync = new(LockRecursionPolicy.SupportsRecursion); // Support recursion for read -> write locks.
@@ -32,12 +34,22 @@ public override void Add(T item1, T item2, params T[] items)
3234
});
3335

3436
/// <inheritdoc />
35-
public override void Add(T[] items)
36-
=> Sync.Write(() =>
37-
{
38-
foreach (T? i in items)
39-
InternalSource.Add(i);
40-
});
37+
public override void AddRange(IEnumerable<T> items)
38+
{
39+
if (items is null) return;
40+
IReadOnlyList<T> enumerable = items switch
41+
{
42+
IImmutableList<T> i => i,
43+
T[] a => a,
44+
_ => items.ToArray(),
45+
};
46+
47+
Sync.Write(() =>
48+
{
49+
foreach (var item in enumerable)
50+
InternalSource.Add(item);
51+
});
52+
}
4153

4254
/// <inheritdoc />
4355
public override void Clear()
@@ -49,7 +61,7 @@ public override bool Contains(T item)
4961

5062
/// <inheritdoc />
5163
public override bool Remove(T item)
52-
=> IfContains(item, c => c.Remove(item));
64+
=> Sync.Write(() => InternalSource.Remove(item));
5365

5466
/// <inheritdoc />
5567
public override int Count

source/Synchronized/ReadWriteSynchronizedListWrapper.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,14 @@ public void Insert(int index, T item)
2929
/// <inheritdoc />
3030
public void RemoveAt(int index)
3131
=> Sync.Write(() => InternalSource.RemoveAt(index));
32+
33+
/// <inheritdoc />
34+
public override bool Remove(T item)
35+
=> Sync.ReadUpgradeable(() =>
36+
{
37+
int i = InternalSource.IndexOf(item);
38+
if (i == -1) return false;
39+
RemoveAt(i);
40+
return true;
41+
});
3242
}

0 commit comments

Comments
 (0)