19
19
20
20
#include "gov.h"
21
21
22
- #define BUCKETS 12
22
+ #define BUCKETS 6
23
23
#define INTERVAL_SHIFT 3
24
24
#define INTERVALS (1UL << INTERVAL_SHIFT)
25
25
#define RESOLUTION 1024
29
29
/*
30
30
* Concepts and ideas behind the menu governor
31
31
*
32
- * For the menu governor, there are 3 decision factors for picking a C
32
+ * For the menu governor, there are 2 decision factors for picking a C
33
33
* state:
34
34
* 1) Energy break even point
35
- * 2) Performance impact
36
- * 3) Latency tolerance (from pmqos infrastructure)
37
- * These three factors are treated independently.
35
+ * 2) Latency tolerance (from pmqos infrastructure)
36
+ * These two factors are treated independently.
38
37
*
39
38
* Energy break even point
40
39
* -----------------------
75
74
* intervals and if the stand deviation of these 8 intervals is below a
76
75
* threshold value, we use the average of these intervals as prediction.
77
76
*
78
- * Limiting Performance Impact
79
- * ---------------------------
80
- * C states, especially those with large exit latencies, can have a real
81
- * noticeable impact on workloads, which is not acceptable for most sysadmins,
82
- * and in addition, less performance has a power price of its own.
83
- *
84
- * As a general rule of thumb, menu assumes that the following heuristic
85
- * holds:
86
- * The busier the system, the less impact of C states is acceptable
87
- *
88
- * This rule-of-thumb is implemented using a performance-multiplier:
89
- * If the exit latency times the performance multiplier is longer than
90
- * the predicted duration, the C state is not considered a candidate
91
- * for selection due to a too high performance impact. So the higher
92
- * this multiplier is, the longer we need to be idle to pick a deep C
93
- * state, and thus the less likely a busy CPU will hit such a deep
94
- * C state.
95
- *
96
- * Currently there is only one value determining the factor:
97
- * 10 points are added for each process that is waiting for IO on this CPU.
98
- * (This value was experimentally determined.)
99
- * Utilization is no longer a factor as it was shown that it never contributed
100
- * significantly to the performance multiplier in the first place.
101
- *
102
77
*/
103
78
104
79
struct menu_device {
@@ -112,19 +87,10 @@ struct menu_device {
112
87
int interval_ptr ;
113
88
};
114
89
115
- static inline int which_bucket (u64 duration_ns , unsigned int nr_iowaiters )
90
+ static inline int which_bucket (u64 duration_ns )
116
91
{
117
92
int bucket = 0 ;
118
93
119
- /*
120
- * We keep two groups of stats; one with no
121
- * IO pending, one without.
122
- * This allows us to calculate
123
- * E(duration)|iowait
124
- */
125
- if (nr_iowaiters )
126
- bucket = BUCKETS /2 ;
127
-
128
94
if (duration_ns < 10ULL * NSEC_PER_USEC )
129
95
return bucket ;
130
96
if (duration_ns < 100ULL * NSEC_PER_USEC )
@@ -138,19 +104,6 @@ static inline int which_bucket(u64 duration_ns, unsigned int nr_iowaiters)
138
104
return bucket + 5 ;
139
105
}
140
106
141
- /*
142
- * Return a multiplier for the exit latency that is intended
143
- * to take performance requirements into account.
144
- * The more performance critical we estimate the system
145
- * to be, the higher this multiplier, and thus the higher
146
- * the barrier to go to an expensive C state.
147
- */
148
- static inline int performance_multiplier (unsigned int nr_iowaiters )
149
- {
150
- /* for IO wait tasks (per cpu!) we add 10x each */
151
- return 1 + 10 * nr_iowaiters ;
152
- }
153
-
154
107
static DEFINE_PER_CPU (struct menu_device , menu_devices ) ;
155
108
156
109
static void menu_update (struct cpuidle_driver * drv , struct cpuidle_device * dev );
@@ -258,8 +211,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
258
211
struct menu_device * data = this_cpu_ptr (& menu_devices );
259
212
s64 latency_req = cpuidle_governor_latency_req (dev -> cpu );
260
213
u64 predicted_ns ;
261
- u64 interactivity_req ;
262
- unsigned int nr_iowaiters ;
263
214
ktime_t delta , delta_tick ;
264
215
int i , idx ;
265
216
@@ -268,8 +219,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
268
219
data -> needs_update = 0 ;
269
220
}
270
221
271
- nr_iowaiters = nr_iowait_cpu (dev -> cpu );
272
-
273
222
/* Find the shortest expected idle interval. */
274
223
predicted_ns = get_typical_interval (data ) * NSEC_PER_USEC ;
275
224
if (predicted_ns > RESIDENCY_THRESHOLD_NS ) {
@@ -283,7 +232,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
283
232
}
284
233
285
234
data -> next_timer_ns = delta ;
286
- data -> bucket = which_bucket (data -> next_timer_ns , nr_iowaiters );
235
+ data -> bucket = which_bucket (data -> next_timer_ns );
287
236
288
237
/* Round up the result for half microseconds. */
289
238
timer_us = div_u64 ((RESOLUTION * DECAY * NSEC_PER_USEC ) / 2 +
@@ -301,7 +250,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
301
250
*/
302
251
data -> next_timer_ns = KTIME_MAX ;
303
252
delta_tick = TICK_NSEC / 2 ;
304
- data -> bucket = which_bucket (KTIME_MAX , nr_iowaiters );
253
+ data -> bucket = which_bucket (KTIME_MAX );
305
254
}
306
255
307
256
if (unlikely (drv -> state_count <= 1 || latency_req == 0 ) ||
@@ -328,15 +277,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
328
277
*/
329
278
if (predicted_ns < TICK_NSEC )
330
279
predicted_ns = data -> next_timer_ns ;
331
- } else {
332
- /*
333
- * Use the performance multiplier and the user-configurable
334
- * latency_req to determine the maximum exit latency.
335
- */
336
- interactivity_req = div64_u64 (predicted_ns ,
337
- performance_multiplier (nr_iowaiters ));
338
- if (latency_req > interactivity_req )
339
- latency_req = interactivity_req ;
280
+ } else if (latency_req > predicted_ns ) {
281
+ latency_req = predicted_ns ;
340
282
}
341
283
342
284
/*
0 commit comments