41
41
* the C state is required to actually break even on this cost. CPUIDLE
42
42
* provides us this duration in the "target_residency" field. So all that we
43
43
* need is a good prediction of how long we'll be idle. Like the traditional
44
- * menu governor, we start with the actual known "next timer event" time.
44
+ * menu governor, we take the actual known "next timer event" time.
45
45
*
46
46
* Since there are other source of wakeups (interrupts for example) than
47
47
* the next timer event, this estimation is rather optimistic. To get a
50
50
* duration always was 50% of the next timer tick, the correction factor will
51
51
* be 0.5.
52
52
*
53
- * menu uses a running average for this correction factor, however it uses a
54
- * set of factors, not just a single factor. This stems from the realization
55
- * that the ratio is dependent on the order of magnitude of the expected
56
- * duration; if we expect 500 milliseconds of idle time the likelihood of
57
- * getting an interrupt very early is much higher than if we expect 50 micro
58
- * seconds of idle time. A second independent factor that has big impact on
59
- * the actual factor is if there is (disk) IO outstanding or not.
60
- * (as a special twist, we consider every sleep longer than 50 milliseconds
61
- * as perfect; there are no power gains for sleeping longer than this)
62
- *
63
- * For these two reasons we keep an array of 12 independent factors, that gets
64
- * indexed based on the magnitude of the expected duration as well as the
65
- * "is IO outstanding" property.
53
+ * menu uses a running average for this correction factor, but it uses a set of
54
+ * factors, not just a single factor. This stems from the realization that the
55
+ * ratio is dependent on the order of magnitude of the expected duration; if we
56
+ * expect 500 milliseconds of idle time the likelihood of getting an interrupt
57
+ * very early is much higher than if we expect 50 micro seconds of idle time.
58
+ * For this reason, menu keeps an array of 6 independent factors, that gets
59
+ * indexed based on the magnitude of the expected duration.
66
60
*
67
61
* Repeatable-interval-detector
68
62
* ----------------------------
69
63
* There are some cases where "next timer" is a completely unusable predictor:
70
64
* Those cases where the interval is fixed, for example due to hardware
71
- * interrupt mitigation, but also due to fixed transfer rate devices such as
72
- * mice.
65
+ * interrupt mitigation, but also due to fixed transfer rate devices like mice.
73
66
* For this, we use a different predictor: We track the duration of the last 8
74
- * intervals and if the stand deviation of these 8 intervals is below a
75
- * threshold value, we use the average of these intervals as prediction.
76
- *
67
+ * intervals and use them to estimate the duration of the next one.
77
68
*/
78
69
79
70
struct menu_device {
@@ -116,53 +107,52 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
116
107
*/
117
108
static unsigned int get_typical_interval (struct menu_device * data )
118
109
{
119
- int i , divisor ;
120
- unsigned int min , max , thresh , avg ;
121
- uint64_t sum , variance ;
122
-
123
- thresh = INT_MAX ; /* Discard outliers above this value */
110
+ s64 value , min_thresh = -1 , max_thresh = UINT_MAX ;
111
+ unsigned int max , min , divisor ;
112
+ u64 avg , variance , avg_sq ;
113
+ int i ;
124
114
125
115
again :
126
-
127
- /* First calculate the average of past intervals */
128
- min = UINT_MAX ;
116
+ /* Compute the average and variance of past intervals. */
129
117
max = 0 ;
130
- sum = 0 ;
118
+ min = UINT_MAX ;
119
+ avg = 0 ;
120
+ variance = 0 ;
131
121
divisor = 0 ;
132
122
for (i = 0 ; i < INTERVALS ; i ++ ) {
133
- unsigned int value = data -> intervals [i ];
134
- if (value <= thresh ) {
135
- sum += value ;
136
- divisor ++ ;
137
- if (value > max )
138
- max = value ;
139
-
140
- if (value < min )
141
- min = value ;
142
- }
123
+ value = data -> intervals [i ];
124
+ /*
125
+ * Discard the samples outside the interval between the min and
126
+ * max thresholds.
127
+ */
128
+ if (value <= min_thresh || value >= max_thresh )
129
+ continue ;
130
+
131
+ divisor ++ ;
132
+
133
+ avg += value ;
134
+ variance += value * value ;
135
+
136
+ if (value > max )
137
+ max = value ;
138
+
139
+ if (value < min )
140
+ min = value ;
143
141
}
144
142
145
143
if (!max )
146
144
return UINT_MAX ;
147
145
148
- if (divisor == INTERVALS )
149
- avg = sum >> INTERVAL_SHIFT ;
150
- else
151
- avg = div_u64 (sum , divisor );
152
-
153
- /* Then try to determine variance */
154
- variance = 0 ;
155
- for (i = 0 ; i < INTERVALS ; i ++ ) {
156
- unsigned int value = data -> intervals [i ];
157
- if (value <= thresh ) {
158
- int64_t diff = (int64_t )value - avg ;
159
- variance += diff * diff ;
160
- }
161
- }
162
- if (divisor == INTERVALS )
146
+ if (divisor == INTERVALS ) {
147
+ avg >>= INTERVAL_SHIFT ;
163
148
variance >>= INTERVAL_SHIFT ;
164
- else
149
+ } else {
150
+ do_div (avg , divisor );
165
151
do_div (variance , divisor );
152
+ }
153
+
154
+ avg_sq = avg * avg ;
155
+ variance -= avg_sq ;
166
156
167
157
/*
168
158
* The typical interval is obtained when standard deviation is
@@ -177,25 +167,40 @@ static unsigned int get_typical_interval(struct menu_device *data)
177
167
* Use this result only if there is no timer to wake us up sooner.
178
168
*/
179
169
if (likely (variance <= U64_MAX /36 )) {
180
- if (((( u64 ) avg * avg > variance * 36 ) && ( divisor * 4 >= INTERVALS * 3 ))
181
- || variance <= 400 ) {
170
+ if ((avg_sq > variance * 36 && divisor * 4 >= INTERVALS * 3 ) ||
171
+ variance <= 400 )
182
172
return avg ;
183
- }
184
173
}
185
174
186
175
/*
187
- * If we have outliers to the upside in our distribution, discard
188
- * those by setting the threshold to exclude these outliers , then
176
+ * If there are outliers, discard them by setting thresholds to exclude
177
+ * data points at a large enough distance from the average , then
189
178
* calculate the average and standard deviation again. Once we get
190
- * down to the bottom 3/4 of our samples, stop excluding samples.
179
+ * down to the last 3/4 of our samples, stop excluding samples.
191
180
*
192
181
* This can deal with workloads that have long pauses interspersed
193
182
* with sporadic activity with a bunch of short pauses.
194
183
*/
195
- if ((divisor * 4 ) <= INTERVALS * 3 )
184
+ if (divisor * 4 <= INTERVALS * 3 ) {
185
+ /*
186
+ * If there are sufficiently many data points still under
187
+ * consideration after the outliers have been eliminated,
188
+ * returning without a prediction would be a mistake because it
189
+ * is likely that the next interval will not exceed the current
190
+ * maximum, so return the latter in that case.
191
+ */
192
+ if (divisor >= INTERVALS / 2 )
193
+ return max ;
194
+
196
195
return UINT_MAX ;
196
+ }
197
+
198
+ /* Update the thresholds for the next round. */
199
+ if (avg - min > max - avg )
200
+ min_thresh = min ;
201
+ else
202
+ max_thresh = max ;
197
203
198
- thresh = max - 1 ;
199
204
goto again ;
200
205
}
201
206
0 commit comments