Skip to content

Commit 5562fe1

Browse files
author
Oren (electricessence)
committed
Much improved benchmark console.
1 parent 365247a commit 5562fe1

5 files changed

Lines changed: 135 additions & 129 deletions

File tree

Open.Disposable.ObjectPools.Tests/ObjectPoolBenchmarks.cs

Lines changed: 0 additions & 86 deletions
This file was deleted.

source/Open.Disposable.ObjectPools.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Part of the "Open" set of libraries.</Description>
2626
</ItemGroup>
2727

2828
<ItemGroup>
29-
<PackageReference Include="Open.Collections" Version="1.2.0" />
29+
<PackageReference Include="Open.Collections" Version="1.2.1" />
3030
<PackageReference Include="Open.Disposable" Version="1.0.4" />
3131
<PackageReference Include="Open.Threading" Version="1.1.5" />
3232
</ItemGroup>

source/OptimisticArrayObjectPool.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ protected override bool GiveInternal(T item)
4040
// Else iterate to find an empty slot.
4141
else
4242
{
43-
var items = _pool;
44-
var len = items?.Length ?? 0;
43+
var elements = _pool;
44+
var len = elements?.Length ?? 0;
4545

4646
for (int i = 0; i < len; i++)
4747
{
48-
// As suggested by Rosyln's implementation, don't worry about interlocking here. It's okay if a few get loose.
49-
if (items[i].Value == null)
48+
var e = elements[i];
49+
// As suggested by Roslyn's implementation, don't worry about interlocking here. It's okay if a few get loose.
50+
if (e.Value == null)
5051
{
51-
items[i].Value = item;
52+
e.Value = item;
5253
return true;
5354
}
5455
}
@@ -66,15 +67,16 @@ protected override T TryTakeInternal()
6667
return item;
6768

6869
// We missed getting the first item or it wasn't there.
69-
var items = _pool;
70-
var len = items?.Length ?? 0;
70+
var elements = _pool;
71+
var len = elements?.Length ?? 0;
7172

7273
for (int i = 0; i < len; i++)
7374
{
74-
item = items[i].Value;
75+
var e = elements[i];
76+
item = e.Value;
7577
if (item != null)
7678
{
77-
if (item == Interlocked.CompareExchange(ref items[i].Value, null, item))
79+
if (item == Interlocked.CompareExchange(ref e.Value, null, item))
7880
{
7981
return item;
8082
}

tester/Benchmark.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ public Benchmark(uint size, uint repeat, Func<IObjectPool<T>> poolFactory)
2424
}
2525

2626
public IEnumerable<TimedResult> TestOnce()
27+
{
28+
var total = TimeSpan.Zero;
29+
foreach(var r in TestOnceInternal())
30+
{
31+
total += r.Duration;
32+
yield return r;
33+
}
34+
35+
yield return new TimedResult("99) TOTAL", total);
36+
}
37+
38+
IEnumerable<TimedResult> TestOnceInternal()
2739
{
2840
var disposeTimer = new Stopwatch();
2941
using (var pool = TimedResult.Measure(out TimedResult constructionTime, "01) Pool Construction", PoolFactory))
@@ -37,7 +49,7 @@ public IEnumerable<TimedResult> TestOnce()
3749
});
3850

3951
var tank = new ConcurrentBag<T>(); // This will have an effect on performance measurement, but hopefully consistently.
40-
//int remaining = 0;
52+
//int remaining = 0;
4153

4254
yield return TimedResult.Measure("03) Take From Empty (In Parallel)", () =>
4355
{
@@ -60,7 +72,7 @@ public IEnumerable<TimedResult> TestOnce()
6072
}
6173
disposeTimer.Stop();
6274

63-
yield return new TimedResult("99) Pool Disposal", disposeTimer);
75+
yield return new TimedResult("98) Pool Disposal", disposeTimer);
6476
}
6577

6678
public IEnumerable<IEnumerable<TimedResult>> TestRepeated()

tester/Program.cs

Lines changed: 109 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Collections.Generic;
77
using System.Diagnostics;
88
using System.Linq;
9+
using System.Text.RegularExpressions;
910
using System.Threading;
1011
using System.Threading.Tasks;
1112

@@ -22,34 +23,114 @@ static void ConsoleNewLine()
2223
Console.WriteLine();
2324
}
2425

25-
const int COUNT = 200;
26-
const int REPEAT = 5000;
27-
28-
static TimedResult[] BenchmarkResults<T>(Func<IObjectPool<T>> poolFactory)
29-
where T : class
30-
{
31-
return Benchmark<T>.Results(COUNT, REPEAT, poolFactory);
32-
}
26+
const int ITERATIONS = 100000;
3327

3428
static TimedResult[] BenchmarkResults<T>(uint count, uint repeat, Func<IObjectPool<T>> poolFactory)
3529
where T : class
3630
{
3731
return Benchmark<T>.Results(count, repeat, poolFactory);
3832
}
3933

40-
static TimedResult[] BenchmarkResults<T>(uint repeat, Func<IObjectPool<T>> poolFactory)
41-
where T : class
34+
static readonly Regex TimeSpanRegex = new Regex(@"((?:00:)+ (?:0\B)?) ([0.]*) (\S*)", RegexOptions.IgnorePatternWhitespace);
35+
36+
static void OutputResult(TimeSpan result)
4237
{
43-
return Benchmark<T>.Results(COUNT, repeat, poolFactory);
38+
var match = TimeSpanRegex.Match(result.ToString());
39+
Console.ForegroundColor = ConsoleColor.Black;
40+
Console.Write(match.Groups[1].Value);
41+
Console.ForegroundColor = ConsoleColor.DarkGray;
42+
Console.Write(match.Groups[2].Value);
43+
Console.ResetColor();
44+
Console.Write(match.Groups[3].Value);
4445
}
4546

46-
static void OutputResults<T>(Func<IObjectPool<T>> poolFactory)
47+
static void OutputResult(TimedResult result, ConsoleColor? labelColor = null)
48+
{
49+
OutputResult(result.Duration);
50+
Console.Write(' ');
51+
if (labelColor.HasValue) Console.ForegroundColor = labelColor.Value;
52+
Console.WriteLine(result.Label.Substring(4));
53+
Console.ResetColor();
54+
}
55+
56+
static void OutputResult(TimedResult result, TimedResult[] all)
57+
{
58+
var duration = result.Duration;
59+
OutputResult(duration);
60+
Console.Write(' ');
61+
var these = all.Where(r => r.Label == result.Label).Select(r=>r.Duration).OrderBy(d=>d).ToArray();
62+
var min = these.First();
63+
var max = these.Last();
64+
if(min!=max)
65+
{
66+
if (duration == min)
67+
Console.ForegroundColor = ConsoleColor.Green;
68+
else if (duration == max)
69+
Console.ForegroundColor = ConsoleColor.Red;
70+
}
71+
Console.WriteLine(result.Label.Substring(4));
72+
Console.ResetColor();
73+
}
74+
75+
static void OutputResults(IEnumerable<TimedResult> results)
76+
{
77+
foreach (var e in results)
78+
OutputResult(e);
79+
80+
ConsoleNewLine();
81+
}
82+
83+
static void OutputResults(IEnumerable<TimedResult> results, TimedResult[] all)
84+
{
85+
foreach (var e in results)
86+
OutputResult(e, all);
87+
88+
ConsoleNewLine();
89+
}
90+
91+
static TimedResult[] OutputResults<T>(uint count, uint repeat, Func<IObjectPool<T>> poolFactory)
4792
where T : class
4893
{
49-
var results = BenchmarkResults(poolFactory);
50-
foreach (var e in BenchmarkResults(poolFactory))
51-
Console.WriteLine(e);
52-
Console.WriteLine("{0} Total", results.Select(r => r.Duration).Aggregate((r1, r2) => r1 + r2));
94+
var results = BenchmarkResults(count, repeat, poolFactory);
95+
OutputResults(results);
96+
return results;
97+
}
98+
99+
static void Test(uint count, uint multiple = 1)
100+
{
101+
var repeat = multiple * ITERATIONS / count;
102+
Console.ForegroundColor = ConsoleColor.Cyan;
103+
Console.WriteLine("Repeat {1:g} for size {0:g}", count, repeat);
104+
ConsoleSeparator();
105+
Console.ResetColor();
106+
ConsoleNewLine();
107+
108+
var cursor = Console.CursorTop;
109+
var results = new List<Tuple<string,TimedResult[]>>(3);
110+
111+
string header;
112+
113+
Console.WriteLine(header = "ConcurrentBagObjectPool.................................");
114+
results.Add(Tuple.Create(header, OutputResults(count, repeat, () => ConcurrentBagObjectPool.Create<object>((int)count * 2))));
115+
116+
Console.WriteLine(header = "LinkedListObjectPool....................................");
117+
results.Add(Tuple.Create(header, OutputResults(count, repeat, () => LinkedListObjectPool.Create<object>((int)count * 2))));
118+
119+
Console.WriteLine(header = "OptimisticArrayObjectPool...............................");
120+
results.Add(Tuple.Create(header, OutputResults(count, repeat, () => OptimisticArrayObjectPool.Create<object>((int)count * 2))));
121+
122+
//Console.WriteLine(header = "BufferBlockObjectPool...................................");
123+
//results.Add(Tuple.Create(header, OutputResults(count, repeat, () => BufferBlockObjectPool.Create<object>((int)count * 2))));
124+
125+
var all = results.SelectMany(r => r.Item2).ToArray();
126+
127+
Console.SetCursorPosition(0, cursor);
128+
129+
foreach(var r in results)
130+
{
131+
Console.WriteLine(r.Item1);
132+
OutputResults(r.Item2, all);
133+
}
53134

54135
ConsoleNewLine();
55136
}
@@ -58,25 +139,22 @@ static void Main(string[] args)
58139
{
59140
Console.Write("Initializing...");
60141

61-
// Run once through first to scramble initial conditions.
62-
BenchmarkResults(100, () => ConcurrentBagObjectPool.Create<object>());
63-
BenchmarkResults(100, () => LinkedListObjectPool.Create<object>());
64-
BenchmarkResults(100, () => OptimisticArrayObjectPool.Create<object>());
65-
// BenchmarkResults(100, () => BufferBlockObjectPool.Create<object>());
142+
// Run once through first to scramble/warm-up initial conditions.
143+
BenchmarkResults(100, 100, () => ConcurrentBagObjectPool.Create<object>(200));
144+
BenchmarkResults(100, 100, () => LinkedListObjectPool.Create<object>(200));
145+
BenchmarkResults(100, 100, () => OptimisticArrayObjectPool.Create<object>(200));
146+
// BenchmarkResults(100, 100, () => BufferBlockObjectPool.Create<object>());
66147

67148
Console.SetCursorPosition(0, Console.CursorTop);
68149

69-
Console.WriteLine("ConcurrentBagObjectPool.................................");
70-
OutputResults(() => ConcurrentBagObjectPool.Create<object>());
71-
72-
Console.WriteLine("LinkedListObjectPool....................................");
73-
OutputResults(() => LinkedListObjectPool.Create<object>());
74-
75-
Console.WriteLine("OptimisticArrayObjectPool...............................");
76-
OutputResults(() => OptimisticArrayObjectPool.Create<object>());
150+
Test(4);
151+
Test(10, 2);
152+
Test(100, 8);
153+
Test(250, 16);
154+
Test(1000, 24);
155+
Test(2000, 32);
156+
Test(4000, 48);
77157

78-
//Console.WriteLine("BufferBlockObjectPool...................................");
79-
//OutputResults(() => BufferBlockObjectPool.Create<object>());
80158

81159
Console.WriteLine("(press any key when finished)");
82160
Console.ReadKey();

0 commit comments

Comments
 (0)