技术开发 频道

CPU负载平衡之--运行队列的load计算

  【IT168技术文档】在每个运行队列struct rq里,load代表当前运行队列的负载,同时还有一个cpu_load[]这样的数组,在我理解,它是一个分级别的代表当前运行队列负载的“替身”。在多cpu调度时,会计算不同的cpu domain的负载,根据不同的index, 会选取相应的cpu_load[]作为当前运行队列的负载返回。

  在每个tick处理函数scheduler_tick()中,会调用update_cpu_load(),来更新当前运行队列的负载,便于后面cpu平衡调度时选取最忙的cpu.比如调度函数find_busiest_group() ,它的工作是:find_busiest_group finds and returns the busiest CPU group within the domain. 它会通过两 个函数source_load()和 target_load()来计算并返回当前运行队列的负载。例如 target_load()是这样的:  

1 static unsigned long target_load(int cpu, int type)
2 {
3     struct rq *rq = cpu_rq(cpu);
4     unsigned long total = weighted_cpuload(cpu);  返回当前run queue的load
5
6     if (type == 0 || !sched_feat(LB_BIAS))
7         return total;
8
9     return max(rq->cpu_load[type-1], total); 返回相应  "替身" 与 运行队列负载的较大者
10 }
11

         这两 个函数会有个参数type,它的目的就是选取相应的cpu_load[]。

  在系统初始化过程中,会把cpu_load默认为0. 有兴趣的朋友可以参考kernel/sched.c sched_init()函数,linux 2.6.28 line:8286,片断代码如下:

  for (j = 0; j < CPU_LOAD_IDX_MAX; j++)

  rq->cpu_load[j] = 0;

  那么后面这个数组是怎么变化的呢?它的变化趋势是什么样子的呢?

  我觉得update_cpu_load()还是比较有意思,来一起分析下。

1 /*
2 * Update rq->cpu_load[] statistics. This function is usually called every
3 * scheduler tick (TICK_NSEC).
4 */
5 static void update_cpu_load(struct rq *this_rq)   //当前运行队列指针作为函数参数
6 {
7         unsigned long this_load = this_rq->load.weight; //当前运行队列的负载值
8         int i, scale;
9
10         this_rq->nr_load_updates++;          //代表load的更新次数    每一个tick都会加1 ,真够忙的。
11
12         /* Update our load: */   //CPU_LOAD_IDX_MAX在运行队列结构体中=5,这儿对5个等级的cpu_load[]进行更新。
13         for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
14                 unsigned long old_load, new_load;
15
16                 /* scale is effectively 1 << i now, and >> i divides by scale */  //请注意,这个scale就是2 的i 次幂。它
17 的值 分别是  1 2 4 8 16
18
19                 old_load = this_rq->cpu_load;  //当前cpu_load[]数组里面的值
20                 new_load = this_load;  //当前运行队列的负载值
21                 /*
22                  * Round up the averaging division if load is increasing. This
23                  * prevents us from getting stuck on 9 if the load is 10, for
24                  * example.
25                  */   round up://目的   如果load是在增长的,不要把余数别浪费了  
26                 if (new_load > old_load)
27                         new_load += scale-1;
28                 this_rq->cpu_load = (old_load*(scale-1) + new_load) >> i;  //这个公式,我会下面分析。它的意思就是根据当前运行队列的负载以及上次cpu_load[]的数值,计算出当前cpu_load[]应该的变化。
29         }
30 }
31

  

0
相关文章