When execute load balance, scheduler calculates local schedule group and busiest schedule group are overloaded or not. If local schedule group has spare capacity but busiest schedule group is overloaded, scheduler forces to load balance between these two groups for new idle CPU. So in the case for idle balance but not new idle CPU, scheduler does not force load balance.
Usually this will not introduce issue for SMP platform, due below code later checks furthermore for average load for schedule groups:
/* * If the local group is busier than the selected busiest group * don't try and pull any tasks. */ if (local->avg_load >= busiest->avg_load) goto out_balanced;
/* * Don't pull any tasks if this group is already above the domain * average load. */ if (local->avg_load >= sds.avg_load) goto out_balanced;
But for asymmetric capacity architecture (Like ARM big.LITTLE system), it introduces one corner case is: the local schedule group is LITTLE core with lower capacity, the busiest schedule group is big core with higher capacity. So busiest schedule group is overloaded and local schedule group has spare capacity, but because LITTLE core have less capacity value so when calculate avg_load the LITTLE core has higher average load than big core. As result, scheduler skips load balance between the two schedule groups; so it misses the chances to migrate tasks from big cluster to little cluster when big cluster is overloaded and LITTLE cluster has idle CPUs.
So this patch checks if it's idle balance and local schedule group has spare capacity and busiest schedule group are overloaded, then force to trigger load balance between them.
Tested this patch with Geekbench on the ARM Juno R2 board for multi-thread case, the score can be improved from 2357 to 2371, so can improve performance ~0.7%.
Signed-off-by: Leo Yan leo.yan@linaro.org --- kernel/sched/fair.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 924adec..937eca2 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7892,8 +7892,8 @@ static struct sched_group *find_busiest_group(struct lb_env *env) goto force_balance;
/* SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */ - if (env->idle == CPU_NEWLY_IDLE && group_has_capacity(env, local) && - busiest->group_no_capacity) + if ((env->idle == CPU_NEWLY_IDLE || env->idle == CPU_IDLE) && + group_has_capacity(env, local) && busiest->group_no_capacity) goto force_balance;
/* Misfitting tasks should be dealt with regardless of the avg load */ -- 1.9.1