Skip to content

Commit 366bec4

Browse files
Cleanup and addition of GetOrAddSafely methods.
1 parent 7a53fb3 commit 366bec4

13 files changed

+411
-441
lines changed

benchmarking/Benchmarks/CollectionBenchmark.cs

Lines changed: 55 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,90 +3,82 @@
33
using System.Collections.Generic;
44
using System.Linq;
55

6-
namespace Open.Collections
6+
namespace Open.Collections;
7+
8+
public class CollectionBenchmark<T> : BenchmarkBase<Func<ICollection<T>>>
79
{
8-
public class CollectionBenchmark<T> : BenchmarkBase<Func<ICollection<T>>>
9-
{
10-
public CollectionBenchmark(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory) : base(size, repeat, factory) => _items = Enumerable.Range(0, (int)TestSize * 2).Select(itemFactory).ToArray();
10+
public CollectionBenchmark(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory) : base(size, repeat, factory) => _items = Enumerable.Range(0, (int)TestSize * 2).Select(itemFactory).ToArray();
1111

12-
protected readonly T[] _items;
12+
protected readonly T[] _items;
1313

14-
protected override IEnumerable<TimedResult> TestOnceInternal()
15-
{
14+
protected override IEnumerable<TimedResult> TestOnceInternal()
15+
{
16+
var c = Param();
1617

17-
var c = Param();
18+
yield return TimedResult.Measure("Fill (.Add(item))", () =>
19+
{
20+
for (var i = 0; i < TestSize; i++) c.Add(_items[i]);
21+
});
1822

19-
yield return TimedResult.Measure("Fill (.Add(item))", () =>
20-
{
21-
for (var i = 0; i < TestSize; i++) c.Add(_items[i]);
22-
});
23+
yield return TimedResult.Measure("Enumerate", () =>
24+
{
25+
// ReSharper disable once NotAccessedVariable
26+
var x = 0;
27+
// ReSharper disable once LoopCanBeConvertedToQuery
28+
foreach (var _ in c) { x++; }
29+
});
2330

24-
yield return TimedResult.Measure("Enumerate", () =>
31+
yield return TimedResult.Measure(".Contains(item)", () =>
32+
{
33+
for (var i = 0; i < TestSize; i++)
2534
{
26-
// ReSharper disable once NotAccessedVariable
27-
var x = 0;
28-
// ReSharper disable once LoopCanBeConvertedToQuery
29-
foreach (var _ in c) { x++; }
30-
});
35+
var _ = c.Contains(_items[i]);
36+
}
37+
});
3138

32-
yield return TimedResult.Measure(".Contains(item)", () =>
39+
if (c is IList<T> list)
40+
{
41+
yield return TimedResult.Measure("IList<T> Read Access", () =>
3342
{
34-
for (var i = 0; i < TestSize; i++)
43+
for (var i = 0; i < TestSize; i += 2)
3544
{
36-
var _ = c.Contains(_items[i]);
45+
var _ = list[i];
3746
}
3847
});
48+
}
3949

40-
if (c is IList<T> list)
41-
{
42-
yield return TimedResult.Measure("IList<T> Read Access", () =>
43-
{
44-
for (var i = 0; i < TestSize; i += 2)
45-
{
46-
var _ = list[i];
47-
}
48-
});
49-
}
50-
51-
yield return TimedResult.Measure("Empty Backwards (.Remove(last))", () =>
52-
{
53-
for (var i = 0; i < TestSize; i++) c.Remove(_items[TestSize - i - 1]);
54-
});
55-
56-
yield return TimedResult.Measure("Refill (.Add(item))", () =>
57-
{
58-
for (var i = 0; i < TestSize; i++) c.Add(_items[i]);
59-
});
60-
61-
yield return TimedResult.Measure("Empty Forwards (.Remove(first))", () =>
62-
{
63-
for (var i = 0; i < TestSize; i++) c.Remove(_items[i]);
64-
});
50+
yield return TimedResult.Measure("Empty Backwards (.Remove(last))", () =>
51+
{
52+
for (var i = 0; i < TestSize; i++) c.Remove(_items[TestSize - i - 1]);
53+
});
6554

55+
yield return TimedResult.Measure("Refill (.Add(item))", () =>
56+
{
6657
for (var i = 0; i < TestSize; i++) c.Add(_items[i]);
58+
});
6759

68-
yield return TimedResult.Measure(".Clear()", () =>
69-
{
70-
c.Clear();
71-
});
72-
73-
}
60+
yield return TimedResult.Measure("Empty Forwards (.Remove(first))", () =>
61+
{
62+
for (var i = 0; i < TestSize; i++) c.Remove(_items[i]);
63+
});
7464

65+
for (var i = 0; i < TestSize; i++) c.Add(_items[i]);
7566

67+
yield return TimedResult.Measure(".Clear()", () => c.Clear());
7668
}
69+
}
7770

78-
public class CollectionBenchmark : CollectionBenchmark<object>
71+
public class CollectionBenchmark : CollectionBenchmark<object>
72+
{
73+
public CollectionBenchmark(uint size, uint repeat, Func<ICollection<object>> factory)
74+
: base(size, repeat, factory, _ => new object())
7975
{
80-
public CollectionBenchmark(uint size, uint repeat, Func<ICollection<object>> factory) : base(size, repeat, factory, i => new object())
81-
{
82-
83-
}
84-
85-
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory) => (new CollectionBenchmark<T>(size, repeat, factory, itemFactory)).Result;
86-
76+
}
8777

88-
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory)
89-
where T : new() => (new CollectionBenchmark<T>(size, repeat, factory, i => new T())).Result;
78+
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory)
79+
=> new CollectionBenchmark<T>(size, repeat, factory, itemFactory).Result;
9080

91-
}
81+
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory)
82+
where T : new()
83+
=> new CollectionBenchmark<T>(size, repeat, factory, _ => new T()).Result;
9284
}

benchmarking/Benchmarks/CollectionParallelBenchmark.cs

Lines changed: 87 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -4,153 +4,118 @@
44
using System.Linq;
55
using System.Threading.Tasks;
66

7-
namespace Open.Collections
7+
namespace Open.Collections;
8+
9+
public class CollectionParallelBenchmark<T> : CollectionBenchmark<T>
810
{
9-
public class CollectionParallelBenchmark<T> : CollectionBenchmark<T>
11+
public CollectionParallelBenchmark(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory) : base(size, repeat, factory, itemFactory)
1012
{
11-
public CollectionParallelBenchmark(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory) : base(size, repeat, factory, itemFactory)
12-
{
13-
14-
}
15-
16-
protected override IEnumerable<TimedResult> TestOnceInternal()
17-
{
13+
}
1814

19-
var c = Param();
15+
protected override IEnumerable<TimedResult> TestOnceInternal()
16+
{
17+
var c = Param();
2018

21-
yield return TimedResult.Measure("Fill (.Add(item)) (In Parallel)", () =>
22-
{
23-
Parallel.For(0, TestSize, i => c.Add(_items[i]));
24-
});
19+
yield return TimedResult.Measure("Fill (.Add(item)) (In Parallel)",
20+
() => Parallel.For(0, TestSize, i => c.Add(_items[i])));
2521

26-
yield return TimedResult.Measure("Enumerate", () =>
27-
{
28-
// ReSharper disable once NotAccessedVariable
29-
var x = 0;
30-
// ReSharper disable once LoopCanBeConvertedToQuery
31-
foreach (var _ in c) { x++; }
32-
});
22+
yield return TimedResult.Measure("Enumerate", () =>
23+
{
24+
// ReSharper disable once NotAccessedVariable
25+
var x = 0;
26+
// ReSharper disable once LoopCanBeConvertedToQuery
27+
foreach (var _ in c) { x++; }
28+
});
3329

34-
// It's obvious to note that you have to 'lock' a collection or acquire a 'snapshot' before enumerating.
35-
yield return TimedResult.Measure("Enumerate (In Parallel)", () =>
36-
{
37-
Parallel.ForEach(c, i => { });
38-
});
30+
// It's obvious to note that you have to 'lock' a collection or acquire a 'snapshot' before enumerating.
31+
yield return TimedResult.Measure("Enumerate (In Parallel)",
32+
() => Parallel.ForEach(c, _ => { }));
3933

40-
yield return TimedResult.Measure(".Contains(item) (In Parallel)", () =>
41-
{
42-
Parallel.For(0, TestSize * 2, i => { var _ = c.Contains(_items[i]); });
43-
});
34+
yield return TimedResult.Measure(".Contains(item) (In Parallel)",
35+
() => Parallel.For(0, TestSize * 2, i => { var _ = c.Contains(_items[i]); }));
4436

45-
if (c is IList<T> list)
37+
if (c is IList<T> list)
38+
{
39+
yield return TimedResult.Measure("IList<T> Read Access", () =>
4640
{
47-
yield return TimedResult.Measure("IList<T> Read Access", () =>
41+
for (var i = 0; i < TestSize; i += 2)
4842
{
49-
for (var i = 0; i < TestSize; i += 2)
50-
{
51-
var _ = list[i];
52-
}
53-
});
43+
var _ = list[i];
44+
}
45+
});
5446

55-
yield return TimedResult.Measure("IList<T> Read Access (In Parallel)", () =>
56-
{
57-
Parallel.For(0, (int)TestSize, i => { var _ = list[i]; });
58-
});
59-
}
47+
yield return TimedResult.Measure("IList<T> Read Access (In Parallel)",
48+
() => Parallel.For(0, (int)TestSize, i => { var _ = list[i]; }));
49+
}
6050

61-
if (c is ISynchronizedCollection<T> syncList)
51+
yield return c is ISynchronizedCollection<T> syncList
52+
? TimedResult.Measure(".Snapshot()", () =>
6253
{
63-
yield return TimedResult.Measure(".Snapshot()", () =>
64-
{
65-
var _ = syncList.Snapshot();
66-
});
67-
}
68-
else
69-
{
70-
yield return TimedResult.Measure(".Snapshot()", () =>
71-
{
72-
var _ = c.ToArray();
73-
});
74-
}
75-
76-
yield return TimedResult.Measure("Empty Backwards (.Remove(last)) (In Parallel)", () =>
54+
var _ = syncList.Snapshot();
55+
})
56+
: TimedResult.Measure(".Snapshot()", () =>
7757
{
78-
Parallel.For(0, TestSize, i => { c.Remove(_items[TestSize - i - 1]); });
58+
var _ = c.ToArray();
7959
});
8060

81-
yield return TimedResult.Measure("Refill (.Add(item)) (In Parallel)", () =>
82-
{
83-
Parallel.For(0, TestSize, i => c.Add(_items[i]));
84-
});
61+
yield return TimedResult.Measure("Empty Backwards (.Remove(last)) (In Parallel)",
62+
() => Parallel.For(0, TestSize, i => c.Remove(_items[TestSize - i - 1])));
8563

86-
yield return TimedResult.Measure("50/50 Mixed Contains/Add (In Parallel)", () =>
87-
{
88-
Parallel.For(0, TestSize, i =>
89-
{
90-
if (i % 2 == 0)
91-
c.Contains(_items[i]);
92-
else
93-
c.Add(_items[i]);
94-
});
95-
});
64+
yield return TimedResult.Measure("Refill (.Add(item)) (In Parallel)",
65+
() => Parallel.For(0, TestSize, i => c.Add(_items[i])));
9666

97-
yield return TimedResult.Measure("10/90 Mixed Contains/Add (In Parallel)", () =>
67+
yield return TimedResult.Measure("50/50 Mixed Contains/Add (In Parallel)",
68+
() => Parallel.For(0, TestSize, i =>
9869
{
99-
Parallel.For(0, TestSize, i =>
100-
{
101-
if (i % 10 == 0)
102-
c.Contains(_items[i]);
103-
else
104-
c.Add(_items[i]);
105-
});
106-
});
107-
108-
yield return TimedResult.Measure("90/10 Mixed Contains/Add (In Parallel)", () =>
70+
if (i % 2 == 0)
71+
c.Contains(_items[i]);
72+
else
73+
c.Add(_items[i]);
74+
}));
75+
76+
yield return TimedResult.Measure("10/90 Mixed Contains/Add (In Parallel)",
77+
() => Parallel.For(0, TestSize, i =>
10978
{
110-
Parallel.For(0, TestSize, i =>
111-
{
112-
if (i % 10 != 9)
113-
c.Contains(_items[i]);
114-
else
115-
c.Add(_items[i]);
116-
});
117-
});
118-
119-
yield return TimedResult.Measure("50/50 Mixed Add/Remove (In Parallel)", () =>
79+
if (i % 10 == 0)
80+
c.Contains(_items[i]);
81+
else
82+
c.Add(_items[i]);
83+
}));
84+
85+
yield return TimedResult.Measure("90/10 Mixed Contains/Add (In Parallel)",
86+
() => Parallel.For(0, TestSize, i =>
12087
{
121-
Parallel.For(0, TestSize, i =>
122-
{
123-
if (i % 2 == 0)
124-
c.Add(_items[i]);
125-
else
126-
c.Remove(_items[i]);
127-
});
128-
});
129-
130-
yield return TimedResult.Measure("Empty Forwards (.Remove(first)) (In Parallel)", () =>
88+
if (i % 10 != 9)
89+
c.Contains(_items[i]);
90+
else
91+
c.Add(_items[i]);
92+
}));
93+
94+
yield return TimedResult.Measure("50/50 Mixed Add/Remove (In Parallel)",
95+
() => Parallel.For(0, TestSize, i =>
13196
{
132-
Parallel.For(0, TestSize, i => { c.Remove(_items[i]); });
133-
});
134-
135-
}
136-
137-
138-
97+
if (i % 2 == 0)
98+
c.Add(_items[i]);
99+
else
100+
c.Remove(_items[i]);
101+
}));
102+
103+
yield return TimedResult.Measure("Empty Forwards (.Remove(first)) (In Parallel)",
104+
() => Parallel.For(0, TestSize, i => c.Remove(_items[i])));
139105
}
106+
}
140107

141-
public class CollectionParallelBenchmark : CollectionParallelBenchmark<object>
108+
public class CollectionParallelBenchmark : CollectionParallelBenchmark<object>
109+
{
110+
public CollectionParallelBenchmark(uint size, uint repeat, Func<ICollection<object>> factory)
111+
: base(size, repeat, factory, _ => new object())
142112
{
143-
public CollectionParallelBenchmark(uint size, uint repeat, Func<ICollection<object>> factory) : base(size, repeat, factory, i => new object())
144-
{
145-
146-
}
147-
148-
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory) => (new CollectionParallelBenchmark<T>(size, repeat, factory, itemFactory)).Result;
149-
150-
151-
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory)
152-
where T : new() => (new CollectionParallelBenchmark<T>(size, repeat, factory, i => new T())).Result;
153-
154113
}
155114

115+
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory)
116+
=> new CollectionParallelBenchmark<T>(size, repeat, factory, itemFactory).Result;
117+
118+
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory)
119+
where T : new()
120+
=> new CollectionParallelBenchmark<T>(size, repeat, factory, _ => new T()).Result;
156121
}

0 commit comments

Comments
 (0)