When a task is running on one CPU, when the task utilization is more than 80% of CPU capacity the task will be considered as a misfit task and should be migrated to higher capacity CPU. But the running task will take more than 200ms for migration, this is caused by long latency to trigger load balance.
The latency is decided by two factors, the first one factor is time interval for schedule domain: busy_factor * balance_interval, by default cluster's schedule domain busy_factor = 32 and balance_interval = 8ms so finally latency is 256ms. If we set busy_factor to 1 from sysfs node for every schedule domain, this will reduce the time interval for load balance.
Besides this, another factor is to trigger active load balance for running task, this can be finished by kicking off an idle balance to pull running task to a big core. In the function nohz_kick_needed() it will check if need to wake up a idle CPU for idle balance, but in previous code it have no any checking for misfit task on rq, so finally will not trigger idle balance. As result we can see the running task is sticking on LITTLE core for long time.
This patch is to add checking misfit task in function nohz_kick_needed(), so make sure if there have misfit task can be quickly pulled to higher capacity CPU.
Tested this patch with Geekbench on the ARM Juno R2 board for multi-thread case, the score can be improved from 2176 to 2281, so can improve performance ~4.8%.
Signed-off-by: Leo Yan leo.yan@linaro.org --- kernel/sched/fair.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index cf56241..dedb3e0 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -8939,6 +8939,10 @@ static inline bool nohz_kick_needed(struct rq *rq) (!energy_aware() || cpu_overutilized(cpu))) return true;
+ /* Do idle load balance if there have misfit task */ + if (energy_aware() && rq->misfit_task) + return true; + rcu_read_lock(); sd = rcu_dereference(per_cpu(sd_busy, cpu)); if (sd && !energy_aware()) { -- 1.9.1