When calculate imbalance between two clusters, then need calculate average load between clusters so finally can easily get to know how much load should be migrated.
Let's see the example for there have two clusters, cluster_A load_avg = 600 and cluster_B load_avg = 200; so the average load cross these two clusters = 400 if both of them have same capacity value.
If cluster_A capacity is 512 and cluster_B capacity is 1024, then that means cluster_B need migrate below load so cluster_A and cluster_B can get same load level:
avg_load(A) - X = avg_load(B) + X * capacity(A) / capacity(B)
avg_load(A) * capacity(B) - avg_load(B) * capacity(B) X = ---------------------------------------------------------- capacity(A) + capacity(B)
The middle level load is:
avg_load(A) * capacity(A) + avg_load(B) * capacity(B) --------------------------------------------------------- capacity(A) + capacity(B)
So finally total_load = avg_load(A) * capacity(A) + avg_load(B) * capacity(B).
Signed-off-by: Leo Yan leo.yan@linaro.org --- kernel/sched/fair.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 353520d..16e1fe2b 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7441,7 +7441,8 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd
next_group: /* Now, start updating sd_lb_stats */ - sds->total_load += sgs->group_load; + sds->total_load += sgs->group_load * sgs->group_capacity / + SCHED_CAPACITY_SCALE / sgs->group_weight; sds->total_capacity += sgs->group_capacity;
sg = sg->next; @@ -7526,7 +7527,7 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds) { unsigned long tmp, capa_now = 0, capa_move = 0; unsigned int imbn = 2; - unsigned long scaled_busy_load_per_task; + unsigned long scaled_busy_load_per_task, scaled_local_load_per_task; struct sg_lb_stats *local, *busiest;
local = &sds->local_stat; @@ -7541,8 +7542,12 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds) (busiest->load_per_task * SCHED_CAPACITY_SCALE) / busiest->group_capacity;
+ scaled_local_load_per_task = + (busiest->load_per_task * SCHED_CAPACITY_SCALE) / + local->group_capacity; + if (busiest->avg_load + scaled_busy_load_per_task >= - local->avg_load + (scaled_busy_load_per_task * imbn)) { + local->avg_load + (scaled_local_load_per_task * imbn)) { env->imbalance = busiest->load_per_task; return; } -- 1.9.1