4242
4343#define ENOUGH_MEASURE 10000
4444#define TEST_TRIES 10
45+ #define NUM_PERCENTILES (100)
4546
4647static 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+
5990static 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