42
42
43
43
#define ENOUGH_MEASURE 10000
44
44
#define TEST_TRIES 10
45
+ #define NUM_PERCENTILES (100)
45
46
46
47
static t_context_t * t ;
47
48
@@ -56,6 +57,36 @@ static void __attribute__((noreturn)) die(void)
56
57
exit (111 );
57
58
}
58
59
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
+
59
90
static void differentiate (int64_t * exec_times ,
60
91
const int64_t * before_ticks ,
61
92
const int64_t * after_ticks )
@@ -64,7 +95,9 @@ static void differentiate(int64_t *exec_times,
64
95
exec_times [i ] = after_ticks [i ] - before_ticks [i ];
65
96
}
66
97
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 )
68
101
{
69
102
for (size_t i = 0 ; i < N_MEASURES ; i ++ ) {
70
103
int64_t difference = exec_times [i ];
@@ -74,6 +107,13 @@ static void update_statistics(const int64_t *exec_times, uint8_t *classes)
74
107
75
108
/* do a t-test on the execution time */
76
109
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
+ }
77
117
}
78
118
}
79
119
@@ -123,6 +163,7 @@ static bool doit(int mode)
123
163
int64_t * exec_times = calloc (N_MEASURES , sizeof (int64_t ));
124
164
uint8_t * classes = calloc (N_MEASURES , sizeof (uint8_t ));
125
165
uint8_t * input_data = calloc (N_MEASURES * CHUNK_SIZE , sizeof (uint8_t ));
166
+ int64_t * percentiles = calloc (NUM_PERCENTILES , sizeof (int64_t ));
126
167
127
168
if (!before_ticks || !after_ticks || !exec_times || !classes ||
128
169
!input_data ) {
@@ -133,14 +174,16 @@ static bool doit(int mode)
133
174
134
175
bool ret = measure (before_ticks , after_ticks , input_data , mode );
135
176
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 );
137
179
ret &= report ();
138
180
139
181
free (before_ticks );
140
182
free (after_ticks );
141
183
free (exec_times );
142
184
free (classes );
143
185
free (input_data );
186
+ free (percentiles );
144
187
145
188
return ret ;
146
189
}
0 commit comments