Skip to content

Commit a5a0809

Browse files
Joel Fernandesrafaeljw
authored andcommitted
cpufreq: schedutil: Make iowait boost more energy efficient
Currently the iowait_boost feature in schedutil makes the frequency go to max on iowait wakeups. This feature was added to handle a case that Peter described where the throughput of operations involving continuous I/O requests [1] is reduced due to running at a lower frequency, however the lower throughput itself causes utilization to be low and hence causing frequency to be low hence its "stuck". Instead of going to max, its also possible to achieve the same effect by ramping up to max if there are repeated in_iowait wakeups happening. This patch is an attempt to do that. We start from a lower frequency (policy->min) and double the boost for every consecutive iowait update until we reach the maximum iowait boost frequency (iowait_boost_max). I ran a synthetic test (continuous O_DIRECT writes in a loop) on an x86 machine with intel_pstate in passive mode using schedutil. In this test the iowait_boost value ramped from 800MHz to 4GHz in 60ms. The patch achieves the desired improved throughput as the existing behavior. [1] https://patchwork.kernel.org/patch/9735885/ Suggested-by: Peter Zijlstra <[email protected]> Suggested-by: Viresh Kumar <[email protected]> Signed-off-by: Joel Fernandes <[email protected]> Acked-by: Viresh Kumar <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 520eccd commit a5a0809

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

kernel/sched/cpufreq_schedutil.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct sugov_cpu {
5353
struct update_util_data update_util;
5454
struct sugov_policy *sg_policy;
5555

56+
bool iowait_boost_pending;
5657
unsigned long iowait_boost;
5758
unsigned long iowait_boost_max;
5859
u64 last_update;
@@ -169,30 +170,54 @@ static void sugov_set_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,
169170
unsigned int flags)
170171
{
171172
if (flags & SCHED_CPUFREQ_IOWAIT) {
172-
sg_cpu->iowait_boost = sg_cpu->iowait_boost_max;
173+
if (sg_cpu->iowait_boost_pending)
174+
return;
175+
176+
sg_cpu->iowait_boost_pending = true;
177+
178+
if (sg_cpu->iowait_boost) {
179+
sg_cpu->iowait_boost <<= 1;
180+
if (sg_cpu->iowait_boost > sg_cpu->iowait_boost_max)
181+
sg_cpu->iowait_boost = sg_cpu->iowait_boost_max;
182+
} else {
183+
sg_cpu->iowait_boost = sg_cpu->sg_policy->policy->min;
184+
}
173185
} else if (sg_cpu->iowait_boost) {
174186
s64 delta_ns = time - sg_cpu->last_update;
175187

176188
/* Clear iowait_boost if the CPU apprears to have been idle. */
177-
if (delta_ns > TICK_NSEC)
189+
if (delta_ns > TICK_NSEC) {
178190
sg_cpu->iowait_boost = 0;
191+
sg_cpu->iowait_boost_pending = false;
192+
}
179193
}
180194
}
181195

182196
static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, unsigned long *util,
183197
unsigned long *max)
184198
{
185-
unsigned long boost_util = sg_cpu->iowait_boost;
186-
unsigned long boost_max = sg_cpu->iowait_boost_max;
199+
unsigned long boost_util, boost_max;
187200

188-
if (!boost_util)
201+
if (!sg_cpu->iowait_boost)
189202
return;
190203

204+
if (sg_cpu->iowait_boost_pending) {
205+
sg_cpu->iowait_boost_pending = false;
206+
} else {
207+
sg_cpu->iowait_boost >>= 1;
208+
if (sg_cpu->iowait_boost < sg_cpu->sg_policy->policy->min) {
209+
sg_cpu->iowait_boost = 0;
210+
return;
211+
}
212+
}
213+
214+
boost_util = sg_cpu->iowait_boost;
215+
boost_max = sg_cpu->iowait_boost_max;
216+
191217
if (*util * boost_max < *max * boost_util) {
192218
*util = boost_util;
193219
*max = boost_max;
194220
}
195-
sg_cpu->iowait_boost >>= 1;
196221
}
197222

198223
#ifdef CONFIG_NO_HZ_COMMON
@@ -264,6 +289,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
264289
delta_ns = time - j_sg_cpu->last_update;
265290
if (delta_ns > TICK_NSEC) {
266291
j_sg_cpu->iowait_boost = 0;
292+
j_sg_cpu->iowait_boost_pending = false;
267293
continue;
268294
}
269295
if (j_sg_cpu->flags & SCHED_CPUFREQ_RT_DL)

0 commit comments

Comments
 (0)