调度子系统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;
}

上一篇:Windows SMBv3 远程拒绝服务 0day 漏洞


下一篇:Rails测试《八》实战功能测试functional test2