// 計算group在給定domain中的imbalance
// 調用路徑:find_busiest_group->calculate_imbalance
// 函數參數:
// sds:sched domain的統計信息
// this_cpu:當前正在運行load balance的cpu
// imbalance:保存imbalance值
// 函數任務:
// 1.計算最忙group內進程的平均負載
// 1.1 公式:最忙group當前的負載量/最忙group當前運行的進程數
// 2.如果最忙group失衡
// 2.1 最忙group內進程的平均負載 = min(最忙group的當前負載,sched doman的平均負載)
// 3.如果最忙group的負載小於domain平均負載,則說明已經平衡,返回
// 4.如果最忙group沒有失衡
// 4.1 計算最忙group超過group容量的進程個數
// 5.計算load balance進行pull的load
// 5.1 pull的load量爲 min(最忙group超過domain平均負載的量,最忙group的超過容量的負載量)
// 6.計算this_cpu所在group與最忙cpu所在group之間的imbalance量
// 6.1 imbalance量爲 min(load balance進行pull的load,當前cpu所在group超過domain平均負載的量)
// 7.如果imbalance不足最忙group中進程的平均負載
// 7.1 進行微調整
static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
unsigned long *imbalance)
{
unsigned long max_pull, load_above_capacity = ~0UL;
//計算最忙group內進程當前的平均負載
sds->busiest_load_per_task /= sds->busiest_nr_running;
//如果最忙group失衡
if (sds->group_imb) {
//則最忙group內進程的平均負載取 min(當前負載、歷史負載)
sds->busiest_load_per_task =
min(sds->busiest_load_per_task, sds->avg_load);
}
//如果最忙group的負載小於平均負載,則說明已平衡
if (sds->max_load < sds->avg_load) {
//imbalance=0
*imbalance = 0;
return fix_small_imbalance(sds, this_cpu, imbalance);
}
//沒有group失衡
if (!sds->group_imb) {
//最忙group超過容量的進程數
load_above_capacity = (sds->busiest_nr_running -
sds->busiest_group_capacity);
load_above_capacity *= (SCHED_LOAD_SCALE * SCHED_LOAD_SCALE);
load_above_capacity /= sds->busiest->cpu_power;
}
//計算load balance進行pull的load
max_pull = min(sds->max_load - sds->avg_load, load_above_capacity);
//計算imbalance
*imbalance = min(max_pull * sds->busiest->cpu_power,
(sds->avg_load - sds->this_load) * sds->this->cpu_power)
/ SCHED_LOAD_SCALE;
//imbalance不足最忙group中進程的平均負載
if (*imbalance < sds->busiest_load_per_task)
return fix_small_imbalance(sds, this_cpu, imbalance);
}
// 查找sched group中最忙的group
// 函數任務:
// 1.遍歷group內所有在線的cpu
// 1.1 獲取cpu對應的rq的當前負載rq->load.weight
// 1.2 如果rq當前只有一個進程,並且負載大於imbalance,繼續1.1
// 1.3 通過cpu power計算cpu的負載
// 1.3.1 爲方便在不同cpu見進行比較
// 1.4 記錄負載最大的cpu
// 2.返回最忙的cpu
// 調用路徑:load_balance->find_busiest_queue
2.1 static struct rq *find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
unsigned long imbalance, const struct cpumask *cpus)
{
struct rq *busiest = NULL, *rq;
unsigned long max_load = 0;
int i;
//遍歷group內的cpu
for_each_cpu(i, sched_group_cpus(group)) {
unsigned long power = power_of(i);
unsigned long capacity = DIV_ROUND_CLOSEST(power, SCHED_LOAD_SCALE);
unsigned long wl;
//cpu在線
if (!cpumask_test_cpu(i, cpus))
continue;
//cpu的rq
rq = cpu_rq(i);
//rq當前的負載
wl = weighted_cpuload(i);
//rq當前只有一個進程,則返回
if (capacity && rq->nr_running == 1 && wl > imbalance)
continue;
//通過cpu power計算cpu的負載
wl = (wl * SCHED_LOAD_SCALE) / power;
//記錄最大負載的cpu
if (wl > max_load) {
max_load = wl;
busiest = rq;
}
}
//返回最忙的cpu
return busiest;
}
// 獲取cpu power
// 函數任務:
// 1.如果cpu沒有對應的group,返回SCHED_LOAD_SCALE
// 2.否則返回對應group的power
2.2 static unsigned long power_of(int cpu)
{
//獲取cpu對應的group
struct sched_group *group = group_of(cpu);
//沒有對應的group,返回SCHED_LOAD_SCALE
if (!group)
return SCHED_LOAD_SCALE;
//否則返回group的power
return group->cpu_power;
}
調度子系統8_負載均衡(五)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.