-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathTestFixture.cs
More file actions
117 lines (99 loc) · 3.24 KB
/
TestFixture.cs
File metadata and controls
117 lines (99 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Configuration;
using Microsoft.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Threading;
namespace unQuery.PerformanceTests
{
[TestFixture]
public abstract class TestFixture
{
internal static bool AssertionsEnabled = true;
internal static TimeSpan TestDuration = TimeSpan.FromMilliseconds(10000);
private double testPercentile = 0.90d;
private string connectionString = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
[OneTimeSetUp]
public void Init()
{
// Increase process priority since this is time sensitive code
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
}
protected SqlConnection GetOpenConnection()
{
var conn = new SqlConnection(connectionString);
conn.Open();
return conn;
}
protected TestResult RunTest(double maxDiff, Action handCoded, Action unQuery)
{
var sw = new Stopwatch();
var handCodedRuntimes = new List<long>();
var unQueryRuntimes = new List<long>();
bool runTest = true;
// Warmup
handCoded();
unQuery();
// Testrunner thread
var testThread = new Thread(() =>
{
int cnt = 0;
while (runTest || cnt % 2 == 1)
{
if (cnt % 2 == 0)
{
sw.Restart();
handCoded();
sw.Stop();
handCodedRuntimes.Add(sw.ElapsedTicks);
}
else
{
sw.Restart();
unQuery();
sw.Stop();
unQueryRuntimes.Add(sw.ElapsedTicks);
}
cnt++;
}
});
testThread.Start();
testThread.Join(TestDuration);
runTest = false;
testThread.Join();
// Sanity check that both code path were run an equal number of times
if (AssertionsEnabled)
Assert.AreEqual(handCodedRuntimes.Count, unQueryRuntimes.Count);
// Extract the Nth percentile results to reduce variance
int testIterations = handCodedRuntimes.Count;
int percentileCount = Convert.ToInt32(testIterations * testPercentile);
var avgHandCodedRuntime = handCodedRuntimes
.OrderBy(x => x)
.Skip((testIterations - percentileCount) / 2)
.Take(percentileCount)
.Average();
var avgUnQueryRuntime = unQueryRuntimes
.OrderBy(x => x)
.Skip((testIterations - percentileCount) / 2)
.Take(percentileCount)
.Average();
var diff = avgUnQueryRuntime - avgHandCodedRuntime;
var diffPercentage = diff / avgHandCodedRuntime * 100;
Trace.WriteLine("Iterations: " + testIterations);
Trace.WriteLine("Hand coded: " + avgHandCodedRuntime.ToString("N") + " ticks");
Trace.WriteLine("unQuery: " + avgUnQueryRuntime.ToString("N") + " ticks");
Trace.WriteLine("unQuery diff: " + diffPercentage.ToString("N") + "% (Max: " + maxDiff.ToString("N") + "%)");
if (AssertionsEnabled)
Assert.Less(diffPercentage, maxDiff, "unQuery difference should be below " + maxDiff.ToString("N") + "%");
return new TestResult {
Iterations = testIterations,
HandcodedAvgRuntimeInMs = avgHandCodedRuntime,
unQueryAvgRuntimeInMs = avgUnQueryRuntime,
unQueryOverheadInPercent = diffPercentage,
MaximumUnQueryOverheadInPercent = maxDiff
};
}
}
}