- 論壇徽章:
- 0
|
cpu 負(fù)載平衡 之 計(jì)算運(yùn)行隊(duì)列和cpu的load
-----wxc200
在每個(gè)運(yùn)行隊(duì)列struct rq里,load代表當(dāng)前運(yùn)行隊(duì)列的負(fù)載,同時(shí)還有一個(gè)cpu_load[]這樣的數(shù)組,它是一個(gè)分級(jí)別的代表當(dāng)前運(yùn)行隊(duì)列負(fù)載的“替身”。在多cpu調(diào)度時(shí),會(huì)計(jì)算不同的cpu domain的負(fù)載,根據(jù)不同的index, 會(huì)選取相應(yīng)的cpu_load[]作為當(dāng)前運(yùn)行隊(duì)列的負(fù)載返回。
在每個(gè)tick處理函數(shù)scheduler_tick()中,會(huì)調(diào)用update_cpu_load(),來更新當(dāng)前運(yùn)行隊(duì)列的負(fù)載,便于后面cpu調(diào)度調(diào)度平衡時(shí)選取最忙的cpu,比如調(diào)度函數(shù)find_busiest_group() ,它的工作是:find_busiest_group finds and returns the busiest CPU group within the domain. 它會(huì)通過兩 個(gè)函數(shù)source_load()和 target_load()來計(jì)算并返回當(dāng)前運(yùn)行隊(duì)列的負(fù)載。這兩 個(gè)函數(shù)會(huì)有個(gè)參數(shù)index,它的目的就是選取相應(yīng)的cpu_load[]。
在系統(tǒng)初始化過程中,會(huì)把cpu_load默認(rèn)為0. 有興趣的朋友可以參考sched.c sched_init()函數(shù),linux 2.6.28 line:8286
for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
rq->cpu_load[j] = 0;
那么后面這個(gè)數(shù)組是怎么變化的呢?它的變化趨勢(shì)是什么樣子的呢?
我覺得update_cpu_load()比較有意思,來一起分析下。
/*
* Update rq->cpu_load[] statistics. This function is usually called every
* scheduler tick (TICK_NSEC).
*/
static void update_cpu_load(struct rq *this_rq)
{
unsigned long this_load = this_rq->load.weight;
//當(dāng)前運(yùn)行隊(duì)列的負(fù)載值
int i, scale;
this_rq->nr_load_updates++;
//代表load的更新次數(shù) 每一個(gè)tick都會(huì)加1 ,真夠忙的。
/* Update our load: */
//CPU_LOAD_IDX_MAX在運(yùn)行隊(duì)列結(jié)構(gòu)體中=5,這兒對(duì)5個(gè)等級(jí)的cpu_load[]進(jìn)行更新。
for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
unsigned long old_load, new_load;
/* scale is effectively 1 << i now, and >> i divides by scale */
//請(qǐng)注意,這個(gè)scale就是2 的i 次冪。它的值 分別是 1 2 4 8 16
old_load = this_rq->cpu_load; 當(dāng)前cpu_load[]數(shù)組里面的值
new_load = this_load; 當(dāng)前運(yùn)行隊(duì)列的負(fù)載值
/*
* Round up the averaging division if load is increasing. This
* prevents us from getting stuck on 9 if the load is 10, for
* example.
*/
// round up:目的 如果load是在增長(zhǎng)的,不要把余數(shù)別浪費(fèi)了
if (new_load > old_load)
new_load += scale-1;
this_rq->cpu_load = (old_load*(scale-1) + new_load) >> i;
//這個(gè)公式,我會(huì)下面分析。它的意思就是根據(jù)當(dāng)前運(yùn)行隊(duì)列的負(fù)載以及上次cpu_load[]的數(shù)值,計(jì)算出當(dāng)前cpu_load[]應(yīng)該的變化。
}
}
現(xiàn)在分析下這個(gè)公式;
假設(shè)級(jí)別為i(0~4),運(yùn)行隊(duì)列的load值M,cpu_load=mi,則每次的計(jì)算遵循如何規(guī)律:
(M-mi)/2^i + mi
i=0: M - mi + mi
i=1: (M - mi)/2 + mi
i=2: (M-mi)/4 + mi
i=3: (M-mi)/8 + mi
i=4: (M-mi)/16 + mi
由此可見,在M遵循上面的變化趨勢(shì)下,等級(jí)為1的變化最為劇列。。。
另外,如果運(yùn)行隊(duì)列的load值比當(dāng)前cpu_load[]的值大,會(huì)對(duì)M的值有個(gè)補(bǔ)償:舉這樣一個(gè)例子,
假如M-mi = 17,對(duì)于計(jì)算i=4,來說,17/16 = 1,余數(shù)為1 ,這樣太浪費(fèi)了,,我要把余數(shù)也計(jì)算進(jìn)來,所以我要在M-mi處理時(shí),
加上(16-1),這樣,就不會(huì)浪費(fèi)余數(shù)了。
具體在系統(tǒng)中這個(gè)函數(shù)是如何變化的呢/ 可以在pc terminal看下: cat /proc/sched_debu,可以看到不同cpu的相應(yīng)數(shù)值
通過加一些調(diào)試信息看下:
/*
* Update rq->cpu_load[] statistics. This function is usually called
every
* scheduler tick (TICK_NSEC).
*/
static void update_cpu_load(struct rq *this_rq)
{
unsigned long this_load = this_rq->load.weight;
int i, scale;
this_rq->nr_load_updates++;
printk("Before calculate: %d\n", this_load);
/* Update our load: */
for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
unsigned long old_load, new_load;
/* scale is effectively 1 << i now, and >> i divides by scale */
old_load = this_rq->cpu_load;
new_load = this_load;
/*
* Round up the averaging division if load is increasing. This
* prevents us from getting stuck on 9 if the load is 10, for
* example.
*/
if (new_load > old_load)
new_load += scale-1;
this_rq->cpu_load = (old_load*(scale-1) + new_load) >> i;
printk(KERN_INFO "old_load = %d,this_rq->cpu_load[%d] = %d, new_load
= %d\n",old_load, i, this_rq->cpu_load, new_load);
}
}
debug information:
Uncompressing
Linux................................................................
[ 0.000000] clockevents_register_notifier: How many notifier
register on clocke?
[ 0.000000] Linux version 2.6.25 (XXXXXXXX-desktop) (gcc
version 4.2.1) #19
[ 0.000000] Linux comes here.....,it will setup timer in pxa3xx...
.....
Total pages4
[ 0.007812] Kernel command line: console=ttyS0,115200 init=/init
android comm_v0
[ 0.007812] PID hash table entries: 512 (order: 9, 2048 bytes)
[ 0.007812] start_kernel:Before arch-init?????
[ 0.007812] init_timers:when pxatimer?
[ 0.007812] init_timers:Here///
[ 0.007812] start_kernel:After initiate cpu-specific tiemrs...
[ 0.007812] clock's name: jiffies
[ 0.007812] start_kernel xa timer routine is here????
[ 0.007812] pxa_timer_init: it's so so so late.........
[ 0.007812] clockevents_register_device: Only call when add pxa
timer????
[ 0.007812] clockevents_do_notify: I want to know how many times
call
[ 0.007812] Console: colour dummy device 80x30
[ 0.007812] Dentry cache hash table entries: 16384 (order: 4, 65536
bytes)
[ 0.007812] Inode-cache hash table entries: 8192 (order: 3, 32768
bytes)
[ 0.007812] Before calculate: 0
[ 0.007812] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.007812] old_load = 0,this_rq->cpu_load[1] = 0, new_load = 0
[ 0.007812] old_load = 0,this_rq->cpu_load[2] = 0, new_load = 0
[ 0.007812] old_load = 0,this_rq->cpu_load[3] = 0, new_load = 0
[ 0.007812] old_load = 0,this_rq->cpu_load[4] = 0, new_load = 0
[ 0.007812] I think it only execute several times................
[ 0.007812] Memory: 116MB = 116MB total
[ 0.007812] Memory: 112640KB available (3548K code, 1080K data,
148K init)
[ 0.007812] SLUB: Genslabs=12, HWalign=32, Order=0-1, MinObjects=4,
CPUs=1, Nod4
[ 0.007812] Calibrating delay loop (skipped)... 622.58 BogoMIPS
preset
[ 0.007812] Mount-cache hash table entries: 512
[ 0.007812] CPU: Testing write buffer coherency: ok
[ 0.007812] net_namespace: 160 bytes
[ 0.015625] Before calculate: 7266
[ 0.015625] old_load = 0,this_rq->cpu_load[0] = 7266, new_load =
7266
[ 0.015625] old_load = 0,this_rq->cpu_load[1] = 3633, new_load =
7267
[ 0.015625] old_load = 0,this_rq->cpu_load[2] = 1817, new_load =
7269
[ 0.015625] old_load = 0,this_rq->cpu_load[3] = 909, new_load =
7273
[ 0.015625] old_load = 0,this_rq->cpu_load[4] = 455, new_load =
7281
[ 0.015625] I think it only execute several times................
...
[ 0.015625] <MAX9724> GPIOs setup done
[ 0.023437] Before calculate: 177522
[ 0.023437] old_load = 7266,this_rq->cpu_load[0] = 177522, new_load
= 177522
[ 0.023437] old_load = 3633,this_rq->cpu_load[1] = 90578, new_load
= 177523
[ 0.023437] old_load = 1817,this_rq->cpu_load[2] = 45744, new_load
= 177525
[ 0.023437] old_load = 909,this_rq->cpu_load[3] = 22986, new_load =
177529
[ 0.023437] old_load = 455,this_rq->cpu_load[4] = 11522, new_load =
177537
[ 0.023437] I think it only execute several times................
...A) and 174 (SCL)
[ 0.023437] I2C: i2c-0: PXA I2C adapter
[ 0.031250] Before calculate: 0
[ 0.031250] old_load = 177522,this_rq->cpu_load[0] = 0, new_load =
0
[ 0.031250] old_load = 90578,this_rq->cpu_load[1] = 45289, new_load
= 0
[ 0.031250] old_load = 45744,this_rq->cpu_load[2] = 34308, new_load
= 0
[ 0.031250] old_load = 22986,this_rq->cpu_load[3] = 20112, new_load
= 0
[ 0.031250] old_load = 11522,this_rq->cpu_load[4] = 10801, new_load
= 0
[ 0.031250] I think it only execute several times................
[ 0.031250] micco(chip id:0x31) detected.
[ 0.031250] GPIO-83 autorequested
[ 0.039062] Before calculate: 0
[ 0.039062] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.039062] old_load = 45289,this_rq->cpu_load[1] = 22644, new_load
= 0
[ 0.039062] old_load = 34308,this_rq->cpu_load[2] = 25731, new_load
= 0
[ 0.039062] old_load = 20112,this_rq->cpu_load[3] = 17598, new_load
= 0
[ 0.039062] old_load = 10801,this_rq->cpu_load[4] = 10125, new_load
= 0
...
[ 0.046875] Before calculate: 355044
[ 0.046875] old_load = 0,this_rq->cpu_load[0] = 355044, new_load =
355044
[ 0.046875] old_load = 22644,this_rq->cpu_load[1] = 188844,
new_load = 355045
[ 0.046875] old_load = 25731,this_rq->cpu_load[2] = 108060,
new_load = 355047
[ 0.046875] old_load = 17598,this_rq->cpu_load[3] = 59779, new_load
= 355051
[ 0.046875] old_load = 10125,this_rq->cpu_load[4] = 31683, new_load
= 355059
[ 0.046875] I think it only execute several times................
...
[ 0.054687] Before calculate: 0
[ 0.054687] old_load = 355044,this_rq->cpu_load[0] = 0, new_load =
0
[ 0.054687] old_load = 188844,this_rq->cpu_load[1] = 94422,
new_load = 0
[ 0.054687] old_load = 108060,this_rq->cpu_load[2] = 81045,
new_load = 0
[ 0.054687] old_load = 59779,this_rq->cpu_load[3] = 52306, new_load
= 0
[ 0.054687] old_load = 31683,this_rq->cpu_load[4] = 29702, new_load
= 0
[ 0.054687] I think it only execute several times................
[ 0.062500] Before calculate: 0
[ 0.062500] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.062500] old_load = 94422,this_rq->cpu_load[1] = 47211, new_load
= 0
[ 0.062500] old_load = 81045,this_rq->cpu_load[2] = 60783, new_load
= 0
[ 0.062500] old_load = 52306,this_rq->cpu_load[3] = 45767, new_load
= 0
[ 0.062500] old_load = 29702,this_rq->cpu_load[4] = 27845, new_load
= 0
[ 0.062500] I think it only execute several times................
[ 0.070312] Before calculate: 0
[ 0.070312] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.070312] old_load = 47211,this_rq->cpu_load[1] = 23605, new_load
= 0
[ 0.070312] old_load = 60783,this_rq->cpu_load[2] = 45587, new_load
= 0
[ 0.070312] old_load = 45767,this_rq->cpu_load[3] = 40046, new_load
= 0
[ 0.070312] old_load = 27845,this_rq->cpu_load[4] = 26104, new_load
= 0
[ 0.070312] I think it only execute several times................
[ 0.078125] Before calculate: 0
[ 0.078125] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.078125] old_load = 23605,this_rq->cpu_load[1] = 11802, new_load
= 0
[ 0.078125] old_load = 45587,this_rq->cpu_load[2] = 34190, new_load
= 0
[ 0.078125] old_load = 40046,this_rq->cpu_load[3] = 35040, new_load
= 0
[ 0.078125] old_load = 26104,this_rq->cpu_load[4] = 24472, new_load
= 0
[ 0.078125] I think it only execute several times................
...
[ 0.085937] Before calculate: 0
[ 0.085937] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.085937] old_load = 11802,this_rq->cpu_load[1] = 5901, new_load
= 0
[ 0.085937] old_load = 34190,this_rq->cpu_load[2] = 25642, new_load
= 0
[ 0.085937] old_load = 35040,this_rq->cpu_load[3] = 30660, new_load
= 0
[ 0.085937] old_load = 24472,this_rq->cpu_load[4] = 22942, new_load
= 0
[ 0.085937] I think it only execute several times................
[ 0.085937] Switched to NOHz mode on CPU #0
[ 0.093750] Before calculate: 0
[ 0.093750] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.093750] old_load = 5901,this_rq->cpu_load[1] = 2950, new_load =
0
[ 0.093750] old_load = 25642,this_rq->cpu_load[2] = 19231, new_load
= 0
[ 0.093750] old_load = 30660,this_rq->cpu_load[3] = 26827, new_load
= 0
[ 0.093750] old_load = 22942,this_rq->cpu_load[4] = 21508, new_load
= 0
[ 0.101562] Before calculate: 0
[ 0.101562] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.101562] old_load = 2950,this_rq->cpu_load[1] = 1475, new_load =
0
[ 0.101562] old_load = 19231,this_rq->cpu_load[2] = 14423, new_load
= 0
[ 0.101562] old_load = 26827,this_rq->cpu_load[3] = 23473, new_load
= 0
[ 0.101562] old_load = 21508,this_rq->cpu_load[4] = 20163, new_load
= 0
[ 0.109375] Before calculate: 0
[ 0.109375] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.109375] old_load = 1475,this_rq->cpu_load[1] = 737, new_load =
0
[ 0.109375] old_load = 14423,this_rq->cpu_load[2] = 10817, new_load
= 0
[ 0.109375] old_load = 23473,this_rq->cpu_load[3] = 20538, new_load
= 0
[ 0.109375] old_load = 20163,this_rq->cpu_load[4] = 18902, new_load
= 0
[ 0.117187] Before calculate: 0
[ 0.117187] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.117187] old_load = 737,this_rq->cpu_load[1] = 368, new_load = 0
[ 0.117187] old_load = 10817,this_rq->cpu_load[2] = 8112, new_load
= 0
[ 0.117187] old_load = 20538,this_rq->cpu_load[3] = 17970, new_load
= 0
[ 0.117187] old_load = 18902,this_rq->cpu_load[4] = 17720, new_load
= 0
[ 0.125000] Before calculate: 0
[ 0.125000] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.125000] old_load = 368,this_rq->cpu_load[1] = 184, new_load = 0
[ 0.125000] old_load = 8112,this_rq->cpu_load[2] = 6084, new_load =
0
[ 0.125000] old_load = 17970,this_rq->cpu_load[3] = 15723, new_load
= 0
[ 0.125000] old_load = 17720,this_rq->cpu_load[4] = 16612, new_load
= 0
[ 0.132812] Before calculate: 0
[ 0.132812] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.132812] old_load = 184,this_rq->cpu_load[1] = 92, new_load = 0
[ 0.132812] old_load = 6084,this_rq->cpu_load[2] = 4563, new_load =
0
[ 0.132812] old_load = 15723,this_rq->cpu_load[3] = 13757, new_load
= 0
[ 0.132812] old_load = 16612,this_rq->cpu_load[4] = 15573, new_load
= 0
[ 0.140625] Before calculate: 0
[ 0.140625] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.140625] old_load = 92,this_rq->cpu_load[1] = 46, new_load = 0
[ 0.140625] old_load = 4563,this_rq->cpu_load[2] = 3422, new_load =
0
[ 0.140625] old_load = 13757,this_rq->cpu_load[3] = 12037, new_load
= 0
[ 0.140625] old_load = 15573,this_rq->cpu_load[4] = 14599, new_load
= 0
[ 0.148437] Before calculate: 0
[ 0.148437] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.148437] old_load = 46,this_rq->cpu_load[1] = 23, new_load = 0
[ 0.148437] old_load = 3422,this_rq->cpu_load[2] = 2566, new_load =
0
[ 0.148437] old_load = 12037,this_rq->cpu_load[3] = 10532, new_load
= 0
[ 0.148437] old_load = 14599,this_rq->cpu_load[4] = 13686, new_load
= 0
[...
[ 0.156250] TCP reno registered
[ 0.156250] Before calculate: 0
[ 0.156250] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.156250] old_load = 23,this_rq->cpu_load[1] = 11, new_load = 0
[ 0.156250] old_load = 2566,this_rq->cpu_load[2] = 1924, new_load =
0
[ 0.156250] old_load = 10532,this_rq->cpu_load[3] = 9215, new_load
= 0
[ 0.156250] old_load = 13686,this_rq->cpu_load[4] = 12830, new_load
= 0
[ 0.164062] Before calculate: 0
[ 0.164062] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.164062] old_load = 11,this_rq->cpu_load[1] = 5, new_load = 0
[ 0.164062] old_load = 1924,this_rq->cpu_load[2] = 1443, new_load =
0
[ 0.164062] old_load = 9215,this_rq->cpu_load[3] = 8063, new_load =
0
[ 0.164062] old_load = 12830,this_rq->cpu_load[4] = 12028, new_load
= 0
[ 0.171875] Before calculate: 0
[ 0.171875] old_load = 0,this_rq->cpu_load[0] = 0, new_load = 0
[ 0.171875] old_load = 5,this_rq->cpu_load[1] = 2, new_load = 0
[ 0.171875] old_load = 1443,this_rq->cpu_load[2] = 1082, new_load =
0
[ 0.171875] old_load = 8063,this_rq->cpu_load[3] = 7055, new_load =
0
[ 0.171875] old_load = 12028,this_rq->cpu_load[4] = 11276, new_load
= 0
[ 0.179687] initcall 0xc0022f2c ran for 93 msecs: inet_init
+0x0/0x2e8()
[ 0.179687] Unpacking initramfs...Before calculate: 1024
[ 0.179687] old_load = 0,this_rq->cpu_load[0] = 1024, new_load =
1024
[ 0.179687] old_load = 2,this_rq->cpu_load[1] = 513, new_load =
1025
[ 0.179687] old_load = 1082,this_rq->cpu_load[2] = 1067, new_load =
1024
[ 0.179687] old_load = 7055,this_rq->cpu_load[3] = 6301, new_load =
1024
[ 0.179687] old_load = 11276,this_rq->cpu_load[4] = 10635, new_load
= 1024
[ 0.187500] Before calculate: 1024
[ 0.187500] old_load = 1024,this_rq->cpu_load[0] = 1024, new_load =
1024
[ 0.187500] old_load = 513,this_rq->cpu_load[1] = 769, new_load =
1025
[ 0.187500] old_load = 1067,this_rq->cpu_load[2] = 1056, new_load =
1024
[ 0.187500] old_load = 6301,this_rq->cpu_load[3] = 5641, new_load =
1024
[ 0.187500] old_load = 10635,this_rq->cpu_load[4] = 10034, new_load
= 1024
[ 0.195312] Before calculate: 1024
[ 0.195312] old_load = 1024,this_rq->cpu_load[0] = 1024, new_load =
1024
[ 0.195312] old_load = 769,this_rq->cpu_load[1] = 897, new_load =
1025
[ 0.195312] old_load = 1056,this_rq->cpu_load[2] = 1048, new_load =
1024
[ 0.195312] old_load = 5641,this_rq->cpu_load[3] = 5063, new_load =
1024
[ 0.195312] old_load = 10034,this_rq->cpu_load[4] = 9470, new_load
= 1024
[ 0.203125] done
.....
[ 0.203125] ashmem: initialized
[ 0.203125] Before calculate: 7266
[ 0.203125] old_load = 1024,this_rq->cpu_load[0] = 7266, new_load =
7266
[ 0.203125] old_load = 897,this_rq->cpu_load[1] = 4082, new_load =
7267
[ 0.203125] old_load = 1048,
........
.......
[ 79.617187] Before calculate: 360213
[ 79.617187] old_load = 360213,this_rq->cpu_load[0] = 360213, new_load = 360213
[ 79.617187] old_load = 360213,this_rq->cpu_load[1] = 360213, new_load = 360213
[ 79.617187] old_load = 360213,this_rq->cpu_load[2] = 360213, new_load = 360213
[ 79.617187] old_load = 360213,this_rq->cpu_load[3] = 360213, new_load = 360213
[ 79.617187] old_load = 360213,this_rq->cpu_load[4] = 360213, new_load = 360213
[ 79.656250] Before calculate: 360213
[ 79.656250] old_load = 360213,this_rq->cpu_load[0] = 360213, new_load = 360213
[ 79.656250] old_load = 360213,this_rq->cpu_load[1] = 360213, new_load = 360213
[ 79.656250] old_load = 360213,this_rq->cpu_load[2] = 360213, new_load = 360213
[ 79.656250] old_load = 360213,this_rq->cpu_load[3] = 360213, new_load = 360213
[ 79.656250] old_load = 360213,this_rq->cpu_load[4] = 360213, new_load = 360213
[ 79.695312] Before calculate: 360213
.......
為了大家看得方便,我把無關(guān) 的啟動(dòng)信息用...代替了。
大家只需要看我添加的打印信息即可。
可以明顯看到,運(yùn)行隊(duì)列的負(fù)載在變化 。
this_rq->load.weight的變化規(guī)律:
初始化0 -->突然變得很大 -->0---->?
通過后面的調(diào)試發(fā)現(xiàn),cpu_load[]數(shù)組的值,總是在盡量地接近運(yùn)行隊(duì)列的load值,,隨著scale增大,接進(jìn)得越慢。。。cpu_load[0]總是與運(yùn)行隊(duì)列的load值相同。
完。
[ 本帖最后由 wxc200 于 2009-3-10 18:13 編輯 ] |
評(píng)分
-
查看全部評(píng)分
|