Skip to content

Commit

Permalink
sched: Allow newidle balancing to bail out of load_balance
Browse files Browse the repository at this point in the history
While doing newidle load balancing, it is possible for new tasks to
arrive, such as with pending wakeups. newidle_balance() already accounts
for this by exiting the sched_domain load_balance() iteration if it
detects these cases. This is very important for minimizing wakeup
latency.

However, if we are already in load_balance(), we may stay there for a
while before returning back to newidle_balance(). This is most
exacerbated if we enter a 'goto redo' loop in the LBF_ALL_PINNED case. A
very straightforward workaround to this is to adjust should_we_balance()
to bail out if we're doing a CPU_NEWLY_IDLE balance and new tasks are
detected.

This was tested with the following reproduction:
- two threads that take turns sleeping and waking each other up are
  affined to two cores
- a large number of threads with 100% utilization are pinned to all
  other cores

Without this patch, wakeup latency was ~120us for the pair of threads,
almost entirely spent in load_balance(). With this patch, wakeup latency
is ~6us.

Signed-off-by: Josh Don <joshdon@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20220609025515.2086253-1-joshdon@google.com
  • Loading branch information
Josh Don authored and Peter Zijlstra committed Jun 13, 2022
1 parent 2ed81e7 commit 792b9f6
Showing 1 changed file with 7 additions and 1 deletion.
8 changes: 7 additions & 1 deletion kernel/sched/fair.c
Original file line number Diff line number Diff line change
Expand Up @@ -9824,9 +9824,15 @@ static int should_we_balance(struct lb_env *env)
/*
* In the newly idle case, we will allow all the CPUs
* to do the newly idle load balance.
*
* However, we bail out if we already have tasks or a wakeup pending,
* to optimize wakeup latency.
*/
if (env->idle == CPU_NEWLY_IDLE)
if (env->idle == CPU_NEWLY_IDLE) {
if (env->dst_rq->nr_running > 0 || env->dst_rq->ttwu_pending)
return 0;
return 1;
}

/* Try to find first idle CPU */
for_each_cpu_and(cpu, group_balance_mask(sg), env->cpus) {
Expand Down

0 comments on commit 792b9f6

Please sign in to comment.