Skip to content

Commit 0c920f9

Browse files
committed
Improve dudect test with cropped time analysis
The original dudect collect all execution times and perform t-tests, which may be affected by outliers. The outliers could be caused by context switches, interrupts, or other system activities. This patch introduces percentile-based cropping to remove outliers. The patch adds a new function "prepare_percentiles()" to compute thresholds using an complementary exponential decay scale. The function is called before the test starts. The patch modifies "update_statistics()" to perform t-tests on cropped execution times by filtering out the outliers.
1 parent 5223a1d commit 0c920f9

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

dudect/fixture.c

+45-2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
#define ENOUGH_MEASURE 10000
4444
#define TEST_TRIES 10
45+
#define NUM_PERCENTILES (100)
4546

4647
static t_context_t *t;
4748

@@ -56,6 +57,36 @@ static void __attribute__((noreturn)) die(void)
5657
exit(111);
5758
}
5859

60+
static int64_t percentile(const int64_t *a_sorted, double which, size_t size)
61+
{
62+
assert(which >= 0 && which <= 1.0);
63+
size_t pos = (size_t) (which * size);
64+
return a_sorted[pos];
65+
}
66+
67+
static int cmp(const int64_t *a, const int64_t *b)
68+
{
69+
return *a - *b;
70+
}
71+
72+
/* This function is used to set different thresholds for cropping measurements.
73+
* To filter out the slowest measurements, we keep only the fastest ones by a
74+
* complementary exponential decay scale as threshold for cropping measurements:
75+
* threshold(x) = 1 - 0.5^(10 * x / N_MEASURES), where x is the counter of the measurement.
76+
* This way we will have more tolerance for the first measurements and less for the last ones.
77+
*/
78+
static void prepare_percentiles(int64_t *exec_times, int64_t *percentiles)
79+
{
80+
qsort(exec_times, N_MEASURES, sizeof(int64_t),
81+
(int (*)(const void *, const void *)) cmp);
82+
83+
for (size_t i = 0; i < NUM_PERCENTILES; i++) {
84+
percentiles[i] = percentile(
85+
exec_times, 1 - (pow(0.5, 10 * (double) (i + 1) / NUM_PERCENTILES)),
86+
N_MEASURES);
87+
}
88+
}
89+
5990
static void differentiate(int64_t *exec_times,
6091
const int64_t *before_ticks,
6192
const int64_t *after_ticks)
@@ -64,7 +95,9 @@ static void differentiate(int64_t *exec_times,
6495
exec_times[i] = after_ticks[i] - before_ticks[i];
6596
}
6697

67-
static void update_statistics(const int64_t *exec_times, uint8_t *classes)
98+
static void update_statistics(const int64_t *exec_times,
99+
uint8_t *classes,
100+
int64_t *percentiles)
68101
{
69102
for (size_t i = 0; i < N_MEASURES; i++) {
70103
int64_t difference = exec_times[i];
@@ -74,6 +107,13 @@ static void update_statistics(const int64_t *exec_times, uint8_t *classes)
74107

75108
/* do a t-test on the execution time */
76109
t_push(t, difference, classes[i]);
110+
111+
/* t-test on cropped execution times, for several cropping thresholds. */
112+
for (size_t j = 0; j < NUM_PERCENTILES; j++) {
113+
if (difference < percentiles[j]) {
114+
t_push(t, difference, classes[i]);
115+
}
116+
}
77117
}
78118
}
79119

@@ -123,6 +163,7 @@ static bool doit(int mode)
123163
int64_t *exec_times = calloc(N_MEASURES, sizeof(int64_t));
124164
uint8_t *classes = calloc(N_MEASURES, sizeof(uint8_t));
125165
uint8_t *input_data = calloc(N_MEASURES * CHUNK_SIZE, sizeof(uint8_t));
166+
int64_t *percentiles = calloc(NUM_PERCENTILES, sizeof(int64_t));
126167

127168
if (!before_ticks || !after_ticks || !exec_times || !classes ||
128169
!input_data) {
@@ -133,14 +174,16 @@ static bool doit(int mode)
133174

134175
bool ret = measure(before_ticks, after_ticks, input_data, mode);
135176
differentiate(exec_times, before_ticks, after_ticks);
136-
update_statistics(exec_times, classes);
177+
prepare_percentiles(exec_times, percentiles);
178+
update_statistics(exec_times, classes, percentiles);
137179
ret &= report();
138180

139181
free(before_ticks);
140182
free(after_ticks);
141183
free(exec_times);
142184
free(classes);
143185
free(input_data);
186+
free(percentiles);
144187

145188
return ret;
146189
}

0 commit comments

Comments
 (0)