調度子系統8_負載均衡(五)

//	計算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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章